【问题标题】:Why would you not use PreserveReferencesHandling in Json.NET?为什么不在 Json.NET 中使用 PreserveReferencesHandling?
【发布时间】:2020-05-31 23:07:13
【问题描述】:

在有许多奶牛和一些农民负责其中一些奶牛的农场中,PreserveReferencesHandling 显着减少了生成的 json 的大小(在这种情况下为 45%)。

public class Farm
{
    public List<Cow> cows;
    public List<Farmer> farmers;
    public List<List<Farmer>> teams;
    ...
}
public class Cow
{
    //Some properties...
}
public class Farmer
{
    public List<Cow> cows;
    ...
}

如果关闭 PreserveReferencesHandling,这可能会导致在 json 中不必要地复制大量奶牛,这取决于可能存在的任何实现,实际上可能会破坏程序,例如因为相等性检查失败。

例如: 没有 PreserveReferencesHandling

// characters: 985
{
  "cows": [
    {"name":"SmallCow"},
    {"name":"Cow"},
    {"name":"BigCow"}
  ],
  "farmers":[
    {"name":"Joe", "cows":[{"name":"SmallCow"}, {"name":"Cow"}]},
    {"name":"Chris", "cows":[{"name":"SmallCow"}, {"name":"BigCow"}]},
    {"name":"Chris Junior", "cows":[{"name":"SmallCow"}, {"name":"BigCow"}]},
    {"name":"Bob", "cows":[{"name":"SmallCow"}, {"name":"Cow"}, {"name":"BigCow"}]}
  ],
  "teams": [
    [{"name":"Joe", "cows":[{"name":"SmallCow"}, {"name":"Cow"}]}, {"name":"Chris", "cows":[{"name":"SmallCow"}, {"name":"BigCow"}]}],
    [{"name":"Chris Junior", "cows":[{"name":"SmallCow"}, {"name":"BigCow"}]}, {"name":"Chris", "cows":[{"name":"SmallCow"}, {"name":"BigCow"}]}],
    [{"name":"Joe", "cows":[{"name":"SmallCow"}, {"name":"Cow"}]},
    {"name":"Chris", "cows":[{"name":"SmallCow"}, {"name":"BigCow"}]},
    {"name":"Chris Junior", "cows":[{"name":"SmallCow"}, {"name":"BigCow"}]},
    {"name":"Bob", "cows":[{"name":"SmallCow"}, {"name":"Cow"}, {"name":"BigCow"}]}]
  ]
}

使用 PreserveReferencesHandling.Objects

// characters: 547
{ 
  "cows": [
    {"$id": 0, "name":"SmallCow"},
    {"$id": 1,"name":"Cow"},
    {"$id": 2,"name":"BigCow"}
  ],
  "farmers":[
    {"$id": 3, "name":"Joe", "cows":[{"$ref": 0}, {"$ref": 1}]},
    {"$id": 4, "name":"Chris", "cows":[{"$ref": 0}, {"$ref": 2}]},
    {"$id": 5, "name":"Chris Junior", "cows":[{"$ref": 0}, {"$ref": 2}]},
    {"$id": 6, "name":"Bob", "cows":[{"$ref": 0}, {"$ref": 1}, {"$ref": 2}]}
  ],
  "teams": [
    [{"$ref" : 3}, {"$ref" : 4}],
    [{"$ref" : 5}, {"$ref" : 4}],
    [{"$ref" : 3}, {"$ref" : 4}, {"$ref" : 5}, {"$ref" : 6}]
  ]
}

这个例子在某种程度上是为了显示差异而设计的,但我认为这种内存节省只会在数据系统变得更加复杂和相互关联时变得更加明显。

PreserveReferenceHandling 的优缺点是什么?哪个设置最有用,PreserveReferenceHandling.Objects、PreserveReferenceHandling.Arrays 还是 PreserveReferenceHandling.All?

【问题讨论】:

    标签: c# json performance serialization json.net


    【解决方案1】:

    为什么不在 Json.NET 中使用 PreserveReferencesHandling?

    PreserveReferencesHandling 行为的一些缺点包括:

    • 它会生成看起来“怪异”的 JSON,其他 JSON 解析器将难以反序列化(这在以不同语言反序列化时尤其会出现问题)。
    • 可能明确希望进行引用处理(例如,消费者特别希望每个实例都是唯一的,而不是引用相同的值)。

    如果您想要性能/简洁,那么某种形式的二进制格式(例如 protobuf)更有意义。 JSON 具有人类可读性和跨语言很大程度上可互操作的优点。使用PreserveReferencesHandling 会大大削弱这两个好处。

    软件开发的本质是权衡。使用PreserveReferencesHandling 有什么好处吗?当然有——这就是它存在的原因。但是,库的作者正确地针对互操作性进行了优化,同时提供了您需要的选项。

    此外,PreserveReferencesHandling 的使用并不总是与其他 Json.NET features “配合得很好”,并且由于跟踪和比较对象的额外工作,它可能会减慢一些序列化/反序列化参考。分析是必要的,以了解您的性能。

    【讨论】:

    • 郑重声明,我从未使用过该选项,也从未见过它在野外使用过(库/框架代码除外)。
    猜你喜欢
    • 2014-06-20
    • 2011-09-17
    • 2012-09-05
    • 2016-11-07
    • 2013-08-10
    • 1970-01-01
    • 1970-01-01
    • 2016-03-03
    • 1970-01-01
    相关资源
    最近更新 更多