C#中JsonSerializer.Deserialize遇带引号的null字符串反序列化失败
处理JSON中带引号的"null"字符串反序列化问题
问题场景
从外部Web服务获取两种JSON格式:
- 正常配置格式(config为对象):
{"config":{"c1":"All","c2":"is peachy"},"message":"We found a config object"}
- 配置为空的格式(config为字符串"null"):
{"config":"null","message":"Config is null"}
需要将这些JSON反序列化为以下C#类型:
public class WebResponse { [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public Config Config { get; set; } public string Message { get; set; } } public class Config { public string C1 { get; set; } public string C2 { get; set; } }
使用System.Text.Json默认反序列化配置时,能正常处理第一种JSON,但处理第二种时会抛出DeserializeUnableToConvertValue异常——因为默认逻辑会把字符串"null"当成string类型,无法转换为Config对象。
解决方案:自定义JSON转换器
通过实现JsonConverter<Config>来处理这种特殊情况:当遇到字符串"null"时,返回null的Config实例;否则正常反序列化Config对象。
1. 实现自定义转换器
public class ConfigConverter : JsonConverter<Config> { public override Config Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 如果当前JSON token是字符串类型 if (reader.TokenType == JsonTokenType.String) { string value = reader.GetString(); // 判断字符串是否为"null",是则返回null if (string.Equals(value, "null", StringComparison.OrdinalIgnoreCase)) { return null; } } // 其他情况正常反序列化为Config对象 return JsonSerializer.Deserialize<Config>(ref reader, options); } public override void Write(Utf8JsonWriter writer, Config value, JsonSerializerOptions options) { // 序列化逻辑按默认处理即可 JsonSerializer.Serialize(writer, value, options); } }
2. 应用转换器
有两种方式可以应用这个转换器:
方式一:添加到JsonSerializerOptions
var options = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, PropertyNameCaseInsensitive = true, // 注册自定义转换器 Converters = { new ConfigConverter() } }; // 处理带"null"字符串的JSON string jsonNoConfig = @"{""config"":""null"",""message"":""Config is null""}"; WebResponse webResponseNoConfig = JsonSerializer.Deserialize<WebResponse>(jsonNoConfig, options); // 处理正常配置的JSON string jsonWithConfig = @"{""config"":{""c1"":""All"",""c2"":""is peachy""},""message"":""We found a config object""}"; WebResponse webResponseWithConfig = JsonSerializer.Deserialize<WebResponse>(jsonWithConfig, options);
方式二:给Config属性添加特性
直接在WebResponse的Config属性上标记转换器:
public class WebResponse { [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonConverter(typeof(ConfigConverter))] public Config Config { get; set; } public string Message { get; set; } }
这种方式不需要修改JsonSerializerOptions,反序列化代码可以保持原有逻辑。
效果验证
添加转换器后,两种JSON格式都能正常反序列化:
- 对于
"config":"null",WebResponse.Config会被设置为null - 对于正常的config对象,
WebResponse.Config会被正确实例化并赋值
内容的提问来源于stack exchange,提问作者surfmuggle
相关产品推荐
相关产品推荐

