我已经和 JSON.net 一起工作了一段时间。 我已经编写了自定义转换器和自定义合约解析器(通常来自 S.O. 和 Newtonsoft 网站上的修改示例),它们工作正常。
挑战在于,除了示例之外,我几乎没有看到关于何时应该使用一个或另一个(或两个)进行处理的解释。 通过我自己的经验,我基本上已经确定合同解决器更简单,所以如果我能用它们做我需要的事情,我就会走这条路;否则,我使用自定义 JsonConverters。 但是,我进一步知道两者有时一起使用,因此概念变得更加不透明。
问题:
- 是否有一个来源可以区分何时使用一个用户与另一个用户? 我发现Newtonsoft文档不清楚两者是如何区分的,或者何时使用其中一个。
- 两者之间的排序管道是什么?
好问题。 我还没有看到一个明确的文档说什么时候应该编写自定义ContractResolver
或自定义JsonConverter
来解决特定类型的问题。 他们确实做不同的事情,但每个人可以解决什么样的问题之间存在一些重叠。 在回答StackOverflow上的问题时,我已经写了相当多的,所以随着时间的推移,情况对我来说变得更加清晰。 以下是我对它的看法。
合约解析器
协定解析器始终由 Json.Net 使用,并在广泛的级别上控制序列化/反序列化行为。 如果设置中未提供自定义解析程序,则使用DefaultContractResolver
。 解析程序负责确定:
- 每种类型具有什么协定(即它是原语、数组/列表、字典、动态、
JObject
、普通旧对象等); - 类型上有哪些属性(如果有的话)以及它们的名称、类型和可访问性是什么;
- 应用了哪些属性(例如
[JsonProperty]
、[JsonIgnore]
、[JsonConverter]
等),以及 - 这些属性应如何影响每个属性(或类)的(反)序列化。
一般来说,如果要跨各种类自定义序列化或反序列化的某些方面,则可能需要使用ContractResolver
来执行此操作。 以下是您可以使用ContractResolver
自定义的一些内容示例:
- 更改用于类型的协定
- 将所有字典序列化为键/值对数组
- 将列表项序列化为常规对象而不是字符串
- 序列化时更改属性名称的大小写
- 对所有属性名称使用驼峰大小写
- 骆驼大小写除字典以外的所有属性名称
- 以编程方式将特性应用于属性,而无需修改类(如果您不控制所述类的源,则特别有用)
- 在没有属性的类上全局使用 JsonConverter
- 将属性重新映射到运行时定义的不同名称
- 允许使用非公共资源库反序列化到公共属性
- 以编程方式取消应用(忽略)应用于某些类的属性
- (可选)在运行时关闭 JsonIgnore 属性
- 使标记为必需的属性(对于 SOAP)对于 JSON 不需要
- 有条件地序列化属性
- 忽略所有类中的只读属性
- 跳过序列化引发异常的属性
引入自定义属性 - 并基于这些属性应用一些自定义行为
- 加密任何类中特别标记的字符串属性
- 在反序列化期间有选择地转义字符串中的 HTML
Json转换器
与ContractResolver
相比,JsonConverter
的重点更窄:它实际上是为了处理单个类型或相关类型的一小部分子集的序列化或反序列化。 此外,它的工作级别低于解析器。 当转换器被赋予对某个类型负责时,它可以完全控制该类型的 JSON 的读取或写入方式:它直接使用JsonReader
和JsonWriter
类来完成它的工作。 换句话说,它可以更改该类型的 JSON形状。 同时,转换器与"大局"分离,并且无法访问上下文信息,例如正在(反)序列化的对象的父级或与之一起使用的属性属性。 以下是您可以使用JsonConverter
解决的一些问题示例:
- 处理反序列化时的对象实例化问题
- 反序列化为接口,使用 JSON 中的信息来决定要实例化的具体类
- 反序列化有时是单个对象,有时是对象数组的 JSON
- 反序列化可以是数组或嵌套数组的 JSON
- 从混合类型数组反序列化时跳过不需要的项目
- 反序列化为缺少默认构造函数的对象
- 更改值的格式或解释方式
- 将十进制值序列化为本地化字符串
- 转换十进制。最小值到空字符串并返回(用于旧系统)
- 使用多种不同格式序列化日期
- 反序列化日期时忽略 UTC 偏移 量
- 序列化类型时 Json.Net 调用
ToString()
- 在不同的 JSON 和对象结构之间进行转换
- 将混合值的嵌套数组反序列化为项列表
- 反序列化具有不同名称的对象数组 序列化
- /反序列化具有复杂键的自定义字典
- 将自定义 IEnumerable 集合序列化为字典
- 将嵌套的 JSON 结构平展为更简单的对象结构
- 将简单的对象结构扩展为更复杂的 JSON 结构
- 仅将对象列表序列化为 ID 列表
- 将包含 GUID 的对象 JSON 列表反序列化为 GUID 列表
- 变通解决此问题(反)序列化特定 .NET 类型
- 序列化 System.Net.IPAddress 引发异常
- 反序列化Microsoft.Xna.Framework.Rectangle 时出现问题