JSON.net ContractResolver 与 JsonConverter [英] JSON.net ContractResolver vs. JsonConverter
问题描述
我使用 JSON.net 已经有一段时间了.我已经编写了自定义转换器和自定义合约解析器(通常来自修改 S.O. 和 Newtonsoft 网站上的示例),它们工作正常.
I've been working with JSON.net for a while. I have written both custom converters and custom contract resolvers (generally from modifying examples on S.O. and the Newtonsoft website), and they work fine.
挑战在于,除了示例之外,我几乎看不到关于何时应该使用其中一个或另一个(或两者)进行处理的解释.根据我自己的经验,我基本上确定合约解析器更简单,所以如果我可以用它们做我需要的,我会这样做;否则,我使用自定义 JsonConverters.但是,我进一步知道两者有时会一起使用,因此这些概念变得更加不透明.
The challenge is, other than examples, I see little explanation as to when I should use one or the other (or both) for processing. Through my own experience, I've basically determined that contract resolvers are simpler, so if I can do what I need with them, I go that way; otherwise, I use custom JsonConverters. But, I further know both are sometimes used together, so the concepts get further opaque.
问题:
- 是否有一个来源可以区分何时使用一个用户和另一个用户?我发现 Newtonsoft 文档不清楚两者的区别或何时使用其中之一.
- 两者之间的排序管道是什么?
推荐答案
好问题.我还没有看到清晰的文档说明您何时应该更喜欢编写自定义 ContractResolver
或自定义 JsonConverter
来解决特定类型的问题.他们确实做不同的事情,但是每个人可以解决的问题类型之间存在一些重叠.在回答 StackOverflow 上的问题时,我已经写了很多,所以随着时间的推移,图片对我来说变得更加清晰了.以下是我的看法.
Great question. I haven't seen a clear piece of documentation that says when you should prefer to write a custom ContractResolver
or a custom JsonConverter
to solve a particular type of problem. They really do different things, but there is some overlap between what kinds of problems can be solved by each. I've written a fair number of each while answering questions on StackOverflow, so the picture has become a little more clear to me over time. Below is my take on it.
Json.Net始终使用合约解析器,并在广泛的层面上控制序列化/反序列化行为.如果设置中没有提供自定义解析器,则 DefaultContractResolver
被使用.解析器负责确定:
A contract resolver is always used by Json.Net, and governs serialization / deserialization behavior at a broad level. If there is not a custom resolver provided in the settings, then the DefaultContractResolver
is used. The resolver is responsible for determining:
- contract 每种类型都有什么(即它是原始类型、数组/列表、字典、动态、
JObject
,普通旧对象等); - 类型上有哪些属性(如果有的话),它们的名称、类型和可访问性是什么;
- 应用了哪些属性(例如
[JsonProperty]
、[JsonIgnore]
、[JsonConverter]
等)、 - 这些属性应如何影响每个属性(或类)的(反)序列化.
- what contract each type has (i.e. is it a primitive, array/list, dictionary, dynamic,
JObject
, plain old object, etc.); - what properties are on the type (if any) and what are their names, types and accessibility;
- what attributes have been applied (e.g.
[JsonProperty]
,[JsonIgnore]
,[JsonConverter]
, etc.), and - how those attributes should affect the (de)serialization of each property (or class).
一般来说,如果您想跨范围广泛的类自定义序列化或反序列化的某些方面,您可能需要使用 ContractResolver
来完成.以下是您可以使用 ContractResolver
自定义的一些示例:
Generally speaking, if you want to customize some aspect of serialization or deserialization across a wide range of classes, you will probably need to use a ContractResolver
to do it. Here are some examples of things you can customize using a ContractResolver
:
- 更改用于类型的合同
与
ContractResolver
相比,JsonConverter
的关注点更窄:它真正旨在处理单个类型或一小部分的序列化或反序列化相关类型.此外,它的工作级别低于解析器.当转换器负责一个类型时,它可以完全控制如何读取或写入该类型的 JSON:它直接使用JsonReader
和JsonWriter
类来完成它的工作.换句话说,它可以更改该类型的 JSON 的 shape.同时,转换器与大图"分离,并且无法访问上下文信息,例如正在(反)序列化的对象的父级或与它一起使用的属性属性.以下是您可以使用JsonConverter
解决的一些问题示例:In contrast to a
ContractResolver
, the focus of aJsonConverter
is more narrow: it is really intended to handle serialization or deserialization for a single type or a small subset of related types. Also, it works at a lower level than a resolver does. When a converter is given responsibility for a type, it has complete control over how the JSON is read or written for that type: it directly usesJsonReader
andJsonWriter
classes to do its job. In other words, it can change the shape of the JSON for that type. At the same time, a converter is decoupled from the "big picture" and does not have access to contextual information such as the parent of the object being (de)serialized or the property attributes that were used with it. Here are some examples of problems you can solve with aJsonConverter
:- 处理反序列化的对象实例化问题
- 反序列化为接口,使用 JSON 中的信息来决定要实例化哪个具体类
- 反序列化有时是单个对象,有时是对象数组的 JSON
- 反序列化可以是数组或嵌套数组的 JSON
- 从混合类型数组反序列化时跳过不需要的项目
- 反序列化为缺少默认构造函数的对象
- 将十进制值序列化为本地化字符串
- 将 decimal.MinValue 转换为空字符串并返回(用于旧系统)
- 用多种不同格式序列化日期
- 在反序列化日期时忽略 UTC 偏移量
- 在序列化类型时让 Json.Net 调用
ToString()
- 将嵌套的混合值数组反序列化为项目列表
- 反序列化具有不同名称的对象数组
- 序列化/反序列化具有复杂键的自定义字典
- 将自定义 IEnumerable 集合序列化为字典
- 将嵌套的 JSON 结构扁平化为更简单的对象结构
- 将简单的对象结构扩展为更复杂的 JSON 结构
- 仅将对象列表序列化为 ID 列表
- 将包含 GUID 的 JSON 对象列表反序列化为 GUID 列表
这篇关于JSON.net ContractResolver 与 JsonConverter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- 处理反序列化的对象实例化问题