我将我的ASP.NET MVC应用程序切换为使用Newtonsoft JsonSerializer来执行我们的JSON序列化,如下所示:
var writer = new JsonTextWriter(HttpContext.Response.Output) { Formatting = Formatting };
var serializer = JsonSerializer.Create();
serializer.Serialize(writer, myData);
这会生成一些具有$ id和$ ref属性的JSON,然后从JSON中删除重复的对象。我知道这是一个很棒的功能,但是阅读这个JSON的客户端不能支持解释这些引用并期望完整的对象存在。我已尝试将PreserveReferencesHandling
上的JsonSerializerSettings
属性设置为每个可能的值,但似乎没有任何区别。
如何禁用$ id和$ ref属性的创建,并让Newtonsoft序列化程序写出整个对象图?
编辑:这是一个示例C#类,我期望的JSON,以及Newtonsoft序列化程序创建的JSON:
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:
{
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' }]
}
由Newtonsoft序列化程序创建的JSON(注意MainImage中添加的$ id参数,引用的对象完全被$ ref参数替换):
{
MainImage: { $id: 1, Id: 1, Url: 'http://contoso.com/product.png' },
AllImages: [{ $ref: 1 },{ Id: 2, Url: 'http://contoso.com/product2.png' }]
}
据我所知,Newtonsoft版本更好(它是DRYer),但是读取此JSON输出的客户端并不了解$ ref的含义。
答案 0 :(得分:24)
我从您的评论中看到,您的课程实际上是用[DataContract(IsReference = true)]
修饰的,因此这就解释了为什么您看到参考信息被添加到您的JSON中。来自JSON.Net documentation on Serialization Attributes:
除了使用内置的Json.NET属性外,Json.NET还会查找SerializableAttribute(如果DefaultContractResolver上的IgnoreSerializableAttribute设置为false)DataContractAttribute,DataMemberAttribute和NonSerializedAttribute ...确定如何序列化和反序列化JSON。
它也说:
注意强>
Json.NET属性优先于标准.NET序列化属性,例如:如果JsonPropertyAttribute和DataMemberAttribute都存在于属性上并且都自定义名称,则将使用JsonPropertyAttribute中的名称。
所以,似乎问题的解决方案很简单:只需将[JsonObject(IsReference = false)]
添加到您的类中,如下所示:
[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; }
}
这将允许您保留WCF属性,但在序列化为JSON时将覆盖引用行为。