【问题标题】:How do I disable object reference creation in the Newtonsoft JSON serializer?如何在 Newtonsoft JSON 序列化程序中禁用对象引用创建?
【发布时间】:2013-10-11 01:48:13
【问题描述】:

我将 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 的客户端无法支持解释这些引用并期望完整的对象存在。我尝试将JsonSerializerSettings 上的PreserveReferencesHandling 属性设置为每个可能的值,但似乎没有任何区别。

如何禁用 $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 的含义。

【问题讨论】:

  • 如果您发布了一些代表您尝试序列化的内容的示例数据以及所需的 JSON 输出,将会很有帮助。
  • @BrianRogers 我已编辑以包含示例代码和数据。
  • 您使用的是哪个 Newtonsoft 版本?因为在一个版本为 5.0.6 的空项目中,我得到了没有 $id 和 $ref 的预期结果...

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


【解决方案1】:

我从您的 cmets 中看到,您的类实际上是用 [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 时覆盖引用行为。

【讨论】:

  • 所以,我相信我想通了。在独立项目中,此代码的工作方式与您描述的一样。但是,我正在使用的对象使用[DataContract(IsReference = true)] 属性进行修饰,因为它们也在 WCF 服务层中使用。我没想到 Newtonsoft JSON 序列化程序实际上会查看 WCF 属性,但我猜它确实如此,即使 PreserveReferencesHandling 设置为 None。知道如何禁用它吗?
  • 我做了和你写的完全一样的事情,我有[DataContract(IsReference = true)][JsonObject(IsReference = false)]的wcf,但仍然使用$id
  • 先生,祝您万岁
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 2017-05-26
  • 1970-01-01
相关资源
最近更新 更多