如何使用Json.Net将字典序列化为其父对象的一部分

我使用Json.Net进行序列化。 我有一个类与字典:

public class Test { public string X { get; set; } public Dictionary<string, string> Y { get; set; } } 

我可以以某种方式序列化这个对象来获得下面的JSON

 { "X" : "value", "key1": "value1", "key2": "value2" } 

哪里“key1”,“key2”是在词典中的键?

如果您使用的是Json.Net 5.0.5或更高版本,并且您愿意将字典的types从Dictionary<string, string>更改为Dictionary<string, object> ,那么实现您想要的一种简单方法是将[JsonExtensionData]属性添加到字典属性中,如下所示:

 public class Test { public string X { get; set; } [JsonExtensionData] public Dictionary<string, object> Y { get; set; } } 

标记字典的键和值将被序列化为父对象的一部分。 好处是,它也适用于反序列化:JSON中与该类成员不匹配的任何属性都将被放入字典中。

实现JsonConverter派生类:应该使用CustomCreationConverter类作为基类来创build自定义对象

草案版本的转换器(error handling可以根据您的需要进行改进):

 internal class TestObjectConverter : CustomCreationConverter<Test> { #region Overrides of CustomCreationConverter<Test> public override Test Create(Type objectType) { return new Test { Y = new Dictionary<string, string>() }; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { writer.WriteStartObject(); // Write properties. var propertyInfos = value.GetType().GetProperties(); foreach (var propertyInfo in propertyInfos) { // Skip the Y property. if (propertyInfo.Name == "Y") continue; writer.WritePropertyName(propertyInfo.Name); var propertyValue = propertyInfo.GetValue(value); serializer.Serialize(writer, propertyValue); } // Write dictionary key-value pairs. var test = (Test)value; foreach (var kvp in test.Y) { writer.WritePropertyName(kvp.Key); serializer.Serialize(writer, kvp.Value); } writer.WriteEndObject(); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JObject jsonObject = JObject.Load(reader); var jsonProperties = jsonObject.Properties().ToList(); var outputObject = Create(objectType); // Property name => property info dictionary (for fast lookup). var propertyNames = objectType.GetProperties().ToDictionary(pi => pi.Name, pi => pi); foreach (var jsonProperty in jsonProperties) { // If such property exists - use it. PropertyInfo targetProperty; if (propertyNames.TryGetValue(jsonProperty.Name, out targetProperty)) { var propertyValue = jsonProperty.Value.ToObject(targetProperty.PropertyType); targetProperty.SetValue(outputObject, propertyValue, null); } else { // Otherwise - use the dictionary. outputObject.Y.Add(jsonProperty.Name, jsonProperty.Value.ToObject<string>()); } } return outputObject; } public override bool CanWrite { get { return true; } } #endregion } 

客户代码:

 var test = new Test { X = "123", Y = new Dictionary<string, string> { { "key1", "value1" }, { "key2", "value2" }, { "key3", "value3" }, } }; string json = JsonConvert.SerializeObject(test, Formatting.Indented, new TestObjectConverter()); var deserializedObject = JsonConvert.DeserializeObject<Test>(json); 

请注意:字典的属性名称和键名之间可能存在冲突。

如果你想这样序列化。 然后,而不是序列化类只是序列化字典,然后你可以在那里添加键值X的“价值”,这样做。

这里的代码示例如何做到这一点:

 var dict = new Dictionary<string, string> {{"x","value"},{"key1", "value1"}, {"key2", "value2"}}; var json = JsonConvert.SerializeObject(dict, Formatting.Indented); 

会返回

 { "X" : "value", "key1": "value1", "key2": "value2" } 

您可以创build此转换器,然后将其分配给您的属性。 采取了一些build议的解决scheme。

 public class DictionaryToJsonObjectConverter : JsonConverter { public override bool CanConvert(Type objectType) { return typeof(IDictionary<string, string>).IsAssignableFrom(objectType); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException(); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { writer.WriteRawValue(JsonConvert.SerializeObject(value, Formatting.Indented)); } } 

然后在你的poco课堂中使用它。

 public class Poco { [JsonProperty("myid")] public string Id{ get; set; } [JsonProperty("properties")] [JsonConverter(typeof(DictionaryToJsonObjectConverter))] public IDictionary<string, string> Properties { get; set; } }