11

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

4

1 回答 1

24

我从您的评论中看到您的类实际上是用 装饰的[DataContract(IsReference = true)],所以这就解释了为什么您看到参考信息被添加到您的 JSON 中。来自关于序列化属性的 JSON.Net 文档

除了使用内置的 Json.NET 属性外,Json.NET 还在确定如何序列化和反序列化 JSON 时查找SerializableAttribute(如果 DefaultContractResolver 上的 IgnoreSerializableAttribute 设置为 false)DataContractAttributeDataMemberAttributeNonSerializedAttribute ...。

它还说:

笔记

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 时覆盖引用行为。

于 2013-10-11T20:25:01.537 回答