c# - serialize - ¿Cómo hacer que el serializador JSON.Net llame a ToString() al serializar un tipo particular?
serializar json c# (3)
No tengo tiempo para probar mi solución, pero debería funcionar. Suponiendo que todas las clases que está usando son las suyas, ¿por qué no hace una anulación de ToString en todas ellas y las clases que necesitan usar el serializador de Newtonsoft.Json pueden ser serializadas dentro del método ToString y devueltas? De esta forma, siempre puede llamar a ToString cuando desee obtener la cadena serializada del objeto.
Estoy usando el serializador Newtonsoft.Json para convertir clases C # a JSON. Para algunas clases no necesito el serializador para una instancia de propiedades individuales, sino que simplemente llamo a ToString en el objeto, es decir,
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public override string ToString() { return string.Format("{0} {1}", FirstName, LastName ); }
}
¿Qué debo hacer para obtener el objeto Persona serializado como resultado de su método ToString ()? Puede que tenga muchas clases como esta, así que no quiero terminar con un serializador específico para la clase Persona, quiero tener uno que pueda ser aplicable a cualquier clase (a través del atributo, supongo).
Simplemente puede probar la biblioteca de constructores JSON de Newtonsoft y Serilaize el objeto de tipo Persona utilizando dicho código:
Dictionary<string, object> collection = new Dictionary<string, object>()
{
{"First", new Person(<add FirstName as constructor>)},
{"Second", new Person(<add LastName as constructor>)},
};
string json = JsonConvert.SerializeObject(collection, Formatting.Indented, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
});
Puede hacerlo fácilmente con un JsonConverter
personalizado:
public class ToStringJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Para usar el convertidor, decore cualquier clase que deba ser serializada como cadena con un atributo [JsonConverter]
como este:
[JsonConverter(typeof(ToStringJsonConverter))]
public class Person
{
...
}
Aquí hay una demostración que muestra el convertidor en acción:
class Program
{
static void Main(string[] args)
{
Company company = new Company
{
CompanyName = "Initrode",
Boss = new Person { FirstName = "Head", LastName = "Honcho" },
Employees = new List<Person>
{
new Person { FirstName = "Joe", LastName = "Schmoe" },
new Person { FirstName = "John", LastName = "Doe" }
}
};
string json = JsonConvert.SerializeObject(company, Formatting.Indented);
Console.WriteLine(json);
}
}
public class Company
{
public string CompanyName { get; set; }
public Person Boss { get; set; }
public List<Person> Employees { get; set; }
}
[JsonConverter(typeof(ToStringJsonConverter))]
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public override string ToString()
{
return string.Format("{0} {1}", FirstName, LastName);
}
}
Salida:
{
"CompanyName": "Initrode",
"Boss": "Head Honcho",
"Employees": [
"Joe Schmoe",
"John Doe"
]
}
Si también necesita poder convertir de cadena a un objeto, puede implementar el método ReadJson
en el convertidor de modo que busque un método public static Parse(string)
y lo llame. Nota: asegúrese de cambiar el método CanRead
del convertidor para que CanRead
true
(o simplemente elimine por completo la sobrecarga CanRead
), de lo ReadJson
, nunca se llamará a ReadJson
.
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
MethodInfo parse = objectType.GetMethod("Parse", new Type[] { typeof(string) });
if (parse != null && parse.IsStatic && parse.ReturnType == objectType)
{
return parse.Invoke(null, new object[] { (string)reader.Value });
}
throw new JsonException(string.Format(
"The {0} type does not have a public static Parse(string) method that returns a {0}.",
objectType.Name));
}
Por supuesto, para que lo anterior funcione, también deberá asegurarse de implementar un método Parse
adecuado en cada clase que está convirtiendo, si es que aún no existe. Para nuestra clase Person
ejemplo que se muestra arriba, ese método podría verse más o menos así:
public static Person Parse(string s)
{
if (string.IsNullOrWhiteSpace(s))
throw new ArgumentException("s cannot be null or empty", "s");
string[] parts = s.Split(new char[] { '' '' }, 2);
Person p = new Person { FirstName = parts[0] };
if (parts.Length > 1)
p.LastName = parts[1];
return p;
}
Demostración de ida y vuelta: https://dotnetfiddle.net/fd4EG4