stringenumconverter serialize serializar newtonsoft net jsonproperty jsonconvert deserializar attribute serialization deserialization json.net

serialization - serialize - serializar y deserializar json c#



Json.NET Uri(de) errores de serialización (1)

Necesito serializar y deserializar un objeto que contiene una propiedad System.Uri utilizando la última (4.0.3) biblioteca Json.NET .

El siguiente código demuestra el problema:

string input = "http://test.com/%22foo+bar%22"; Uri uri = new Uri(input); string json = JsonConvert.SerializeObject(uri); Uri output = JsonConvert.DeserializeObject<Uri>(json);

El método DeserializeObject arroja una JsonReaderException. Esto funciona bien con 4.0.2.

He enviado un problema en codeplex con pruebas y parches para solucionar el problema, pero parece que al autor le lleva un poco liberar una versión fija.

Mientras tanto, ¿hay algo que pueda hacer (usar JsonSettings o cualquier otra cosa) para que la última versión funcione como se esperaba?

Algunas opciones que tengo hasta ahora:

  1. apegarse a 4.0.2 - los nuevos paquetes nuget dependen de 4.0.3
  2. cambiar uri a cadena - prefiero ir con la opción 1 y las dependencias de pkg gestionadas manualmente
  3. usar compilación personalizada con el parche aplicado: esto es lo que estoy haciendo ahora, pero odio la idea de anular los ensamblajes del paquete nuget.

Puede escribir una clase de ayuda que evite el manejo habitual de System.Uri y lo trate Uri.OriginalString como una cadena, utilizando la propiedad Uri.OriginalString .

Aquí hay un ejemplo de código que hace exactamente eso con una clase de convertidor derivada de JsonConverter de JsonConverter .

Propiedad de OriginalString (System.Uri) @ MSDN

Una advertencia es que debe actualizar todos los lugares donde usa JsonConvert para incluir la clase auxiliar como uno de los parámetros adicionales de JsonConverter .

También agregué un ejemplo usando Uri como una variable miembro en una clase, para demostrar que uno no necesariamente tendría que anular los atributos en una clase, aunque podría ser más conveniente para usted. De ser así, podría usar [JsonConverter(UriConverter)] como atributo en los miembros que lo necesiten.

using Newtonsoft.Json; namespace JsonUriSerializeTest { class Program { public class UriConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType.Equals(typeof(Uri)); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.String) { return new Uri((string)reader.Value); } if (reader.TokenType == JsonToken.Null) { return null; } throw new InvalidOperationException("Unhandled case for UriConverter. Check to see if this converter has been applied to the wrong serialization type."); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (null == value) { writer.WriteNull(); return; } if (value is Uri) { writer.WriteValue(((Uri)value).OriginalString); return; } throw new InvalidOperationException("Unhandled case for UriConverter. Check to see if this converter has been applied to the wrong serialization type."); } } public class UriPair { public string label { get; set; } public Uri first { get; set; } public Uri second { get; set; } public void Display() { Console.WriteLine(string.Format("label: {0}", label)); Console.WriteLine(string.Format("first: {0}", first)); Console.WriteLine(string.Format("second: {0}", second)); } } static void Main(string[] args) { string input = "http://test.com/%22foo+bar%22"; Uri uri = new Uri(input); string json = JsonConvert.SerializeObject(uri, new UriConverter()); Uri output = JsonConvert.DeserializeObject<Uri>(json, new UriConverter()); Console.WriteLine(input); Console.WriteLine(output.ToString()); Console.WriteLine(); UriPair pair = new UriPair(); pair.label = input; pair.first = null; pair.second = new Uri(input); string jsonPair = JsonConvert.SerializeObject(pair, new UriConverter()); UriPair outputPair = JsonConvert.DeserializeObject<UriPair>(jsonPair, new UriConverter()); outputPair.Display(); Console.WriteLine(); Console.ReadKey(); } } }