如何在Newtonsoft JSON序列化程序中禁用对象引用创建?

时间:2013-10-11 01:48:14

标签: c# asp.net json json.net

我将我的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的含义。

1 个答案:

答案 0 :(得分:24)

我从您的评论中看到,您的课程实际上是用[DataContract(IsReference = true)]修饰的,因此这就解释了为什么您看到参考信息被添加到您的JSON中。来自JSON.Net documentation on Serialization Attributes

  

除了使用内置的Json.NET属性外,Json.NET还会查找SerializableAttribute(如果DefaultContractResolver上的IgnoreSerializableAttribute设置为false)DataContractAttributeDataMemberAttributeNonSerializedAttribute ...确定如何序列化和反序列化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时将覆盖引用行为。