una - en c# qué es método
¿Cómo desactivo la creación de referencia de objetos en el serializador Newtonsoft JSON? (1)
Usando JSON.Net 5.0.6 (la última versión en NuGet) en su configuración predeterminada, no veo el comportamiento que está viendo. Aquí está el programa exacto que estoy usando para probar:
class Program
{
static void Main(string[] args)
{
Image image1 = new Image { Id = 1, Url = "http://contoso.com/product1.png" };
Image image2 = new Image { Id = 2, Url = "http://contoso.com/product2.png" };
Product product = new Product
{
MainImage = image1,
AllImages = new List<Image> { image1, image2 }
};
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
var writer = new JsonTextWriter(sw) { Formatting = Formatting.Indented };
var serializer = JsonSerializer.Create();
serializer.Serialize(writer, product);
Console.WriteLine(sb.ToString());
}
public class Product
{
public Image MainImage { get; set; }
public List<Image> AllImages { get; set; }
}
public class Image
{
public int Id { get; set; }
public string Url { get; set; }
}
}
Y aquí está el resultado:
{
"MainImage": {
"Id": 1,
"Url": "http://contoso.com/product1.png"
},
"AllImages": [
{
"Id": 1,
"Url": "http://contoso.com/product1.png"
},
{
"Id": 2,
"Url": "http://contoso.com/product2.png"
}
]
}
Sin embargo, si creo una instancia de JsonSerializerSettings
, establezco el valor de PreserveReferencesHandling
en Objects
y paso esas configuraciones al serializador de esta manera:
JsonSerializerSettings settings = new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.Objects
};
var serializer = JsonSerializer.Create(settings);
... luego veo los ID de referencia de los que estás hablando:
{
"$id": "1",
"MainImage": {
"$id": "2",
"Id": 1,
"Url": "http://contoso.com/product1.png"
},
"AllImages": [
{
"$ref": "2"
},
{
"$id": "3",
"Id": 2,
"Url": "http://contoso.com/product2.png"
}
]
}
Si hago lo mismo pero establezco PreserveReferencesHandling
en None
, vuelve a la salida original. Dijiste que "has probado todos los valores diferentes de PreserveReferencesHandling
". ¿Cómo estás haciendo esto en tu código? En su pregunta, no veo que haya pasado ninguna configuración al serializador. Si intenta ejecutar el programa de prueba independiente anterior, ¿obtiene el mismo resultado?
ACTUALIZAR
Veo por sus comentarios que sus clases están decoradas con [DataContract(IsReference = true)]
, por lo que esto explica por qué está viendo que la información de referencia se agrega a su JSON. De la documentación de JSON.Net sobre Atributos de serialización :
Además de usar los atributos incorporados de Json.NET, Json.NET también busca el SerializableAttribute (si IgnoreSerializableAttribute en DefaultContractResolver se establece en falso) DataContractAttribute , DataMemberAttribute y NonSerializedAttribute ... al determinar cómo se serializará y se deserializará JSON.
También dice esto:
Nota
Los atributos Json.NET toman presidencia sobre los atributos de serialización .NET estándar, por ejemplo, si ambos JsonPropertyAttribute y DataMemberAttribute están presentes en una propiedad y ambos personalizan el nombre, se usará el nombre de JsonPropertyAttribute.
Por lo tanto, parece que la solución a su problema es simple: simplemente agregue [JsonObject(IsReference = false)]
a sus clases de esta manera:
[DataContract(IsReference = true)]
[JsonObject(IsReference = false)]
public class Product
{
[DataMember]
public Image MainImage { get; set; }
[DataMember]
public List<Image> AllImages { get; set; }
}
[DataContract(IsReference = true)]
[JsonObject(IsReference = false)]
public class Image
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Url { get; set; }
}
Esto le permitirá mantener sus atributos WCF en su lugar, pero anulará el comportamiento de referencia cuando sea el momento de serializar a JSON. Si ejecuta nuevamente el programa de ejemplo en esta configuración, se soluciona el problema.
Cambié mi aplicación ASP.NET MVC para usar el Newtonsoft JsonSerializer para hacer nuestra serialización JSON, como tal:
var writer = new JsonTextWriter(HttpContext.Response.Output) { Formatting = Formatting };
var serializer = JsonSerializer.Create();
serializer.Serialize(writer, myData);
Esto genera un JSON que tiene propiedades $ id y $ ref y luego elimina objetos duplicados del JSON. Sé que es una característica que es genial, pero los clientes que leen este JSON no pueden soportar la interpretación de estas referencias y esperan que haya objetos completos allí. Intenté establecer la propiedad PreserveReferencesHandling
en JsonSerializerSettings
en todos los valores posibles y no parece hacer ninguna diferencia.
¿Cómo puedo desactivar la creación de las propiedades $ id y $ ref y obtener el serializador de Newtonsoft para escribir todo el gráfico de objetos?
EDITAR : aquí hay una clase C # de ejemplo, el JSON que espero, y el JSON creado por el serializador de Newtonsoft:
public class Product
{
public Image MainImage { get; set; }
public List<Image> AllImages { get; set; }
}
public class Image
{
public int Id { get; set; }
public string Url { get; set; }
}
JSON, espero:
{
MainImage: { Id: 1, Url: ''http://contoso.com/product.png'' },
AllImages: [{ Id: 1, Url: ''http://contoso.com/product.png'' },{ Id: 2, Url: ''http://contoso.com/product2.png'' }]
}
JSON creado por el serializador de Newtonsoft (tenga en cuenta el parámetro $ id agregado en la imagen principal y el objeto al que se hace referencia está completamente reemplazado por un parámetro $ ref):
{
MainImage: { $id: 1, Id: 1, Url: ''http://contoso.com/product.png'' },
AllImages: [{ $ref: 1 },{ Id: 2, Url: ''http://contoso.com/product2.png'' }]
}
Entiendo que la versión de Newtonsoft es mejor (es DRYer) pero el cliente que lee esta salida JSON no entiende lo que significa $ ref.