c# serialization json.net

c# - Cómo serializar un diccionario como parte de su objeto principal utilizando Json.Net



serialization (3)

Implementar la clase CustomCreationConverter : la clase CustomCreationConverter debe usar como clase base para crear un objeto personalizado .

Versión preliminar del convertidor (el manejo de errores puede mejorarse como desee):

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 }

Codigo del cliente:

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);

Tenga en cuenta que existe una posible colisión entre los nombres de propiedad y los nombres de clave del diccionario.

Estoy usando Json.Net para la serialización. Tengo una clase con un diccionario:

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

¿Puedo de alguna manera serializar este objeto para obtener el siguiente JSON

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

donde "key1", "key2" son claves en el Diccionario?


Puede crear este convertidor y luego asignarlo a su propiedad. Tomó algunas partes de las soluciones propuestas.

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)); } }

Entonces úsalo en tu clase poco.

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


Si está utilizando Json.Net 5.0.5 o posterior y está dispuesto a cambiar el tipo de su diccionario de Dictionary<string, string> a Dictionary<string, object> , entonces una manera fácil de lograr lo que quiere es para agregar el atributo [JsonExtensionData] a la propiedad del diccionario de esta manera:

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

Las claves y valores del diccionario marcado se serializarán como parte del objeto principal. La ventaja es que también funciona en la deserialización: cualquier propiedad del JSON que no coincida con los miembros de la clase se colocará en el diccionario.