This is probably something really simple and I looked everywhere and tried everything I could come up with. So I apologize if this is a simple search and I was just looking for
Under normal circumstances, you could define your data
property as a List
, like so:
[DataMember(Name = "data", IsRequired = true)]
public List> data { get; set; }
Then you would be able to serialize and deserialize it successfully with Json.NET. Unfortunately, one of your data objects has duplicated keys:
{
"groupId":"group1",
"failbackAction":"null",
"normal":"null",
"failoverAction":"null",
"failbackAction":"null",
"failoverAction":"null",
"artifactId":"mywebserver",
"normalState":"null"
},
Using duplicated keys is not recommended by the JSON standard, which states:
When the names within an object are not unique, the behavior of software that receives such an object is unpredictable.
In addition, c# dictionaries of course do not support duplicated keys, and data contract serialization does not duplicated property names.
However, it is possible to read a JSON object with duplicated keys using Json.NET's JsonReader and create a custom JsonConverter to handle duplicated keys.
First, define the following class to replace JsonValue. JsonValue
is a silverlight-specific class whose use has been deprecated in overall .Net:
[JsonConverter(typeof(JsonValueListConverter))]
public sealed class JsonValueList
{
public JsonValueList()
{
this.Values = new List>();
}
public List> Values { get; private set; }
}
class JsonValueListConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(JsonValueList).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var jsonValue = (existingValue as JsonValueList ?? new JsonValueList());
if (reader.TokenType != JsonToken.StartObject)
throw new JsonSerializationException("Invalid reader.TokenType " + reader.TokenType);
while (reader.Read())
{
switch (reader.TokenType)
{
case JsonToken.Comment:
break;
case JsonToken.PropertyName:
{
var key = reader.Value.ToString();
if (!reader.Read())
throw new JsonSerializationException(string.Format("Missing value at path: {0}", reader.Path));
var value = serializer.Deserialize(reader);
jsonValue.Values.Add(new KeyValuePair(key, value));
}
break;
case JsonToken.EndObject:
return jsonValue;
default:
throw new JsonSerializationException(string.Format("Unknown token {0} at path: {1} ", reader.TokenType, reader.Path));
}
}
throw new JsonSerializationException(string.Format("Unclosed object at path: {0}", reader.Path));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var jsonValue = (JsonValueList)value;
writer.WriteStartObject();
foreach (var pair in jsonValue.Values)
{
writer.WritePropertyName(pair.Key);
writer.WriteValue(pair.Value);
}
writer.WriteEndObject();
}
}
Notice the use of [JsonConverter(typeof(JsonValueListConverter))]. This specifies the use of a custom converter when serializing and deserializing JsonValueList
.
Next, define your Update_DB
class as follows:
[DataContract]
public class Update_DB
{
[DataMember(Name = "appname", IsRequired = true)]
public string appname { get; set; }
[DataMember]
public string key { get; set; }
[DataMember(Name = "data", IsRequired = true)]
public List data { get; set; }
[DataMember]
public string updateId { get; set; }
[DataMember]
public string updateTS { get; set; }
[DataMember]
public string creationUser { get; set; }
}
Now you will be able to serialize and deserialize your JSON successfully. Sample fiddle.
Update
If you do not have duplicated keys, you can define your class as follows:
[DataContract]
public class Update_DB
{
[DataMember(Name = "appname", IsRequired = true)]
public string appname { get; set; }
[DataMember]
public string key { get; set; }
[DataMember(Name = "data", IsRequired = true)]
public List> data { get; set; }
[DataMember]
public string updateId { get; set; }
[DataMember]
public string updateTS { get; set; }
[DataMember]
public string creationUser { get; set; }
}
And then the following:
var collection = new Update_DB
{
data = new List>
{
new Dictionary
{
{"data1", "10551296"},
{"data2", "TrainingIns"},
{"data3", "Completed"},
},
new Dictionary
{
{"connectorType", "webserver-to-appserver"},
{"sourceUri", "data4"},
{"destinationUri", "data5"},
},
},
};
string x = JsonConvert.SerializeObject(collection.data, Formatting.Indented);
Console.WriteLine(x);
Produces the output:
[ { "data1": "10551296", "data2": "TrainingIns", "data3": "Completed" }, { "connectorType": "webserver-to-appserver", "sourceUri": "data4", "destinationUri": "data5" } ]
Sample fiddle.