Cuando uso Json.Net, entiendo cómo obtener la propiedad $ type en el json representado, pero ¿hay alguna manera de cambiar ese nombre de campo? Necesito usar "__type" en lugar de "$ type".
Respuesta
Parece que esto está codificado como public const string TypePropertyName = "$type";
en Newtonsoft.Json.Serialization.JsonTypeReflector
desafortunadamente, la clase estática interna.
Lo necesitaba yo mismo, y lo único que se me ocurre es tener una versión personalizada modificada de json.net. Lo cual es, por supuesto, una gran pita.
Desafortunadamente, he tenido que abandonar por completo el camino al que me dirigía debido a qué tan difícil es usar Json.Net en muchos casos. Esto es sólo un ejemplo. –
Yo mismo estoy buscando cómo en el lado del servidor, que está escrito i C# y usa Json.NET, puede deserializar JSON enviado desde una aplicación de Android usando Jackson. En Jackson puedo configurar para usar "$ type", pero no funciona de todos modos. – Ted
http://json.codeplex.com/workitem/22429
"yo preferiría quedarse con $ Tipo codificado y consistente."
¿De acuerdo con lo que me pregunto?
http://json.codeplex.com/workitem/21989
yo más bien no - creo que esto es demasiado específico para mí y no me quiero ir por la borda con los ajustes. En algún momento probablemente implemente esto - http://json.codeplex.com/workitem/21856 - permitiendo que personas lean/escriban sus propias propiedades meta en el JSON y usted podría volver a implementar el manejo del nombre del tipo con un nuevo nombre de propiedad. La otra opción es solo modificar el código fuente para que usted tenga ese nombre de propiedad.
Esta es mi solución ...
json.Replace("\"$type\": \"", "\"type\": \"");
¡Su solución es asombrosa!^_^ –
Vea también: https://github.com/JamesNK/Newtonsoft.Json/issues/1331 – manuc66
Tuvimos una necesidad para esto, así que creé una costumbre JsonReader. Estamos utilizando el reposo en nuestros servicios web de MS con modelos de datos complejos y necesitamos reemplazar la propiedad "__type" con "$ type".
class MSJsonReader : JsonTextReader
{
public MSJsonTextReader(TextReader reader) : base(reader) { }
public override bool Read()
{
var hasToken = base.Read();
if (hasToken && base.TokenType == JsonToken.PropertyName && base.Value != null && base.Value.Equals("__type"))
base.SetToken(JsonToken.PropertyName, "$type");
return hasToken;
}
}
Así es como lo utilizamos.
using(JsonReader jr = new MSJsonTextReader(sr))
{
JsonSerializer s = new JsonSerializer();
s.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
s.NullValueHandling = NullValueHandling.Ignore;
s.TypeNameHandling = TypeNameHandling.Auto; // Important!
s.Binder = new MSRestToJsonDotNetSerializationBinder("Server.DataModelsNamespace", "Client.GeneratedModelsNamespace");
T deserialized = s.Deserialize<T>(jr);
return deserialized;
}
Aquí es nuestro MSRestToJsonDotNetSerializationBinder que completa la compatibilidad entre la EM descanso y Json.Net.
class MSRestToJsonDotNetSerializationBinder : System.Runtime.Serialization.SerializationBinder
{
public string ServiceNamespace { get; set; }
public string LocalNamespace { get; set; }
public MSRestToJsonDotNetSerializationBinder(string serviceNamespace, string localNamespace)
{
if (serviceNamespace.EndsWith("."))
serviceNamespace = serviceNamespace.Substring(0, -1);
if(localNamespace.EndsWith("."))
localNamespace = localNamespace.Substring(0, -1);
ServiceNamespace = serviceNamespace;
LocalNamespace = localNamespace;
}
public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
{
assemblyName = null;
typeName = string.Format("{0}:#{1}", serializedType.Name, ServiceNamespace); // MS format
}
public override Type BindToType(string assemblyName, string typeName)
{
string jsonDotNetType = string.Format("{0}.{1}", LocalNamespace, typeName.Substring(0, typeName.IndexOf(":#")));
return Type.GetType(jsonDotNetType);
}
}
no hay otra opción que permite serializar tipo personalizado nombre de la propiedad en Json.NET
. La idea es no escribir la propiedad predeterminada $type
, sino introducir el nombre del tipo como propiedad de la clase.
Supongamos que tenemos una clase Location
:
public class Location
{
public double Latitude { get; set; }
public double Longitude { get; set; }
}
En primer lugar, es necesario introducir tipo de nombre de la propiedad y modificar la clase como se demuestra a continuación:
public class Location
{
[JsonProperty("__type")]
public string EntityTypeName
{
get
{
var typeName = string.Format("{0}, {1}", GetType().FullName, GetType().Namespace);
return typeName;
}
}
public double Latitude { get; set; }
public double Longitude { get; set; }
}
A continuación, establezca JsonSerializerSettings.TypeNameHandling
-TypeNameHandling.None
para que el deserializador omita la representación del atributo predeterminado $type
.
Eso es todo.
Ejemplo
var point = new Location() { Latitude = 51.5033630, Longitude = -0.1276250 };
var jsonLocation = JsonConvert.SerializeObject(point, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.None, //do not write type property(!)
});
Console.WriteLine(jsonLocation);
Resultado
{"__type":"Namespace.Location, Namespace","Latitude":51.503363,"Longitude":-0.127625}
No veo cómo deserializar determinará el tipo correcto con su solución. ¿Puedes explicar? –
Para deserializar, intente con 'JsonCreationConverter', p. ver http://stackoverflow.com/questions/8030538 – xmedeko
al serializar, no es una buena manera de anular el nombre de la propiedad:
public class CustomJsonWriter : JsonTextWriter
{
public CustomJsonWriter(TextWriter writer) : base(writer)
{
}
public override void WritePropertyName(string name, bool escape)
{
if (name == "$type") name = "__type";
base.WritePropertyName(name, escape);
}
}
var serializer = new JsonSerializer();
var writer = new StreamWriter(stream) { AutoFlush = true };
serializer.Serialize(new CustomJsonWriter(writer), objectToSerialize);
No he probado deserialización aún, pero en peor de los casos que podría utilizar:
json.Replace("\"__type": \"", "\"type\": \"$type\");
que tenía que hacer esto para mi interfaz de usuario API REST como nombres angularjs disregards campos comenzando con un signo de dólar ($).
Así que aquí es una solución que cambia el nombre de $type
-__type
para toda la Web API y trabaja tanto para la serialización y deserialización.
Con el fin de poder utilizar una costumbre JsonWriter
y una costumbre JsonReader
(como se propone en las otras respuestas a esta pregunta), tenemos que heredar el JsonMediaTypeFormatter
y anular los métodos correspondientes:
internal class CustomJsonNetFormatter : JsonMediaTypeFormatter
{
public override JsonReader CreateJsonReader(Type type, Stream readStream, Encoding effectiveEncoding)
{
return new CustomJsonReader(readStream, effectiveEncoding);
}
public override JsonWriter CreateJsonWriter(Type type, Stream writeStream, Encoding effectiveEncoding)
{
return new CustomJsonWriter(writeStream, effectiveEncoding);
}
private class CustomJsonWriter : JsonTextWriter
{
public CustomJsonWriter(Stream writeStream, Encoding effectiveEncoding)
: base(new StreamWriter(writeStream, effectiveEncoding))
{
}
public override void WritePropertyName(string name, bool escape)
{
if (name == "$type") name = "__type";
base.WritePropertyName(name, escape);
}
}
private class CustomJsonReader : JsonTextReader
{
public CustomJsonReader(Stream readStream, Encoding effectiveEncoding)
: base(new StreamReader(readStream, effectiveEncoding))
{
}
public override bool Read()
{
var hasToken = base.Read();
if (hasToken && TokenType == JsonToken.PropertyName && Value != null && Value.Equals("__type"))
{
SetToken(JsonToken.PropertyName, "$type");
}
return hasToken;
}
}
}
De Por supuesto, debe registrar el formateador personalizado en su WebApiConfig
. Así que reemplazamos el formateador Json.NET predeterminado por uno personalizado:
config.Formatters.Remove(config.Formatters.JsonFormatter);
config.Formatters.Add(new CustomJsonNetFormatter());
Listo.
También podría hacerlo de esta manera:
[JsonConverter(typeof(JsonSubtypes), "ClassName")]
public class Annimal
{
public virtual string ClassName { get; }
public string Color { get; set; }
}
Tendrá el convertidor JsonSubtypes
que no es parte de Newtonsoft.Json
proyecto.
- 1. Propiedades de cambio de nombre de Json.net
- 2. JSON.NET - Deserialización de tipo condicional
- 3. Cambiar el nombre del campo de error en Rails
- 4. TFS "Copiar" el valor de un campo a otro
- 5. mongodb tipo cambiar a matriz
- 6. Rieles: cómo usar before_save para cambiar un valor de campo basado en otro campo?
- 7. Conversión de un BufferedImage a otro tipo
- 8. Cambiar Tipo de Propiedad
- 9. atributo dependiente de otro campo
- 10. ClearCase: cambiar el nombre de tipo de rama?
- 11. ¿Cómo deserializar usando JSON.Net a un tipo anónimo?
- 12. cambiar a otro usuario usando tela
- 13. Quiero cambiar la tecla 'devolver' de la clave virtual de iphone a otro nombre
- 14. Json.NET, no se puede deserializar tipo nulable
- 15. Genéricos de advertencia T tiene mismo nombre que el tipo de otro tipo
- 16. Apache mod_rewrite redirigir el tipo de archivo a otro dominio
- 17. MySQL como otro campo
- 18. ¿Cómo obtengo el nombre de JsonProperty en JSON.Net?
- 19. ¿Cómo crear un nuevo tipo System.String con otro nombre?
- 20. Tutorial de JSON.NET
- 21. iCloud: cambiar el nombre de los documentos abiertos en otro dispositivo a veces falla
- 22. Cambiar el nombre de mis.paquetes a mi.paquete
- 23. El uso de la advertencia de eclipse "declaración de campo oculta otro campo o variable"?
- 24. Cambiar el nombre del campo en JSON usando Jackson
- 25. Cambiar a otro espacio (MacOSX) programáticamente
- 26. Anulación del manejo predeterminado de tipo primitivo en Json.Net
- 27. Lanzando un doble a otro tipo numérico
- 28. Cambiar el foco de un widget de texto a otro
- 29. Hacer un campo único en función de otro campo
- 30. Usando JSON.Net para escribir un nombre de propiedad
Necesito esto también, por ejemplo [JSON-LD] (http://json-ld.org) usa '@ type' –