CosmosClient使用System.Text.Json自定义转换器失效排查
场景
- 已在Azure上创建CosmosDB容器;
- 定义了用于读写数据的
MyClass类,其中MyType类型字段标注了System.Text.Json的自定义转换器[JsonConverter(typeof(MyTypeJsonConverter))]; - 分别实现了System.Text.Json和Newtonsoft.Json版本的自定义转换器,单独用
JsonSerializer.Deserialize测试时,两种转换器都能正常完成序列化/反序列化; - 使用
CosmosClient读写数据时,配置了CosmosSerializationOptions。
问题
使用Newtonsoft.Json版本的转换器时,CosmosClient操作正常;但使用System.Text.Json版本的转换器时,抛出Newtonsoft.Json.JsonSerializationException异常,提示无法将字符串转换为MyType,且异常未触发转换器的Read/Write方法,看起来CosmosClient没有识别到属性上标注的转换器。
疑问
- 是否存在明显错误?
- 是否需要注册自定义转换器?如果需要,最简洁的方式是什么?(避免实现完整的自定义序列化器)
解答
1. 明显错误分析
核心问题是序列化器版本不匹配:
CosmosClient默认使用Newtonsoft.Json作为序列化器,如果你配置CosmosSerializationOptions时没有明确指定System.Text.Json,生效的序列化器还是Newtonsoft.Json;- Newtonsoft.Json无法识别
System.Text.Json.Serialization.JsonConverterAttribute这个属性,自然不会触发你写的System.Text.Json版本转换器,最终抛出Newtonsoft.Json的序列化异常。
2. 注册自定义转换器的简洁方式
要让CosmosClient识别System.Text.Json的自定义转换器,有两种简洁实现方式:
方式一:全局注册(推荐,无需修改实体类)
创建CosmosClient时,明确指定使用System.Text.Json序列化器,并添加自定义转换器:
var cosmosClient = new CosmosClient(connectionString, new CosmosClientOptions { SerializerOptions = new CosmosSerializationOptions { Serializer = new CosmosSystemTextJsonSerializer( new JsonSerializerOptions { Converters = { new MyTypeJsonConverter() } }) } });
方式二:保留实体类属性标注,匹配序列化器
如果你想保留实体类上的[JsonConverter]标注,只需确保CosmosClient使用System.Text.Json序列化器即可,属性标注会被自动识别:
var cosmosClient = new CosmosClient(connectionString, new CosmosClientOptions { SerializerOptions = new CosmosSerializationOptions { Serializer = new CosmosSystemTextJsonSerializer() } });
关键注意点
- 不要混用两种序列化器的转换器和属性标注:Newtonsoft.Json对应
Newtonsoft.Json.JsonConverterAttribute,System.Text.Json对应System.Text.Json.Serialization.JsonConverterAttribute,二者不能交叉使用; - 若要继续用Newtonsoft.Json序列化器,就把实体类的属性标注换成Newtonsoft.Json版本的转换器属性。
内容的提问来源于stack exchange,提问作者jeancallisti
相关产品推荐
相关产品推荐

