如何将Json反序列化为string/double/null简单类型而非JsonElement?需自定义转换器吗?
问题描述
我的JSON结构如下,值仅可为字符串、数值或null:
attributes: { "value1": "name", "value2": 123, "value3": null }
反序列化时,字典里的值会被转成JsonElement类型,有没有办法让它始终反序列化为简单类型(string、double或null)?是否需要自定义转换器?
示例代码:
using System; using System.Collections.Generic; using System.Text.Json; public class Root { public IDictionary<string, object> attributes {get;set;} } public class Program { public static void Main() { var json = "{\"attributes\":{\"value1\":\"something\",\"value2\":123}}"; var o = JsonSerializer.Deserialize<Root>(json); Console.WriteLine(o.attributes["value1"].GetType()); // 输出: System.Text.Json.JsonElement } }
解决方案
没错,得靠自定义转换器来解决这个问题——默认情况下System.Text.Json会把object类型的JSON值转成JsonElement,要拿到string、double或null这类简单类型,就得自己写转换器处理。
具体步骤
- 编写自定义字典转换器
这个转换器会逐个处理字典里的键值对,根据JSON的类型把JsonElement转成对应的简单类型:
using System; using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; public class SimpleTypeDictionaryConverter : JsonConverter<IDictionary<string, object>> { public override IDictionary<string, object> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.StartObject) { throw new JsonException("预期是JSON对象的起始"); } var dictionary = new Dictionary<string, object>(); while (reader.Read() && reader.TokenType != JsonTokenType.EndObject) { var key = reader.GetString(); reader.Read(); object value = reader.TokenType switch { JsonTokenType.String => reader.GetString(), JsonTokenType.Number => reader.GetDouble(), JsonTokenType.Null => null, _ => throw new JsonException($"不支持的JSON类型:{reader.TokenType}") }; dictionary.Add(key, value); } return dictionary; } public override void Write(Utf8JsonWriter writer, IDictionary<string, object> value, JsonSerializerOptions options) { writer.WriteStartObject(); foreach (var kvp in value) { writer.WritePropertyName(kvp.Key); JsonSerializer.Serialize(writer, kvp.Value, options); } writer.WriteEndObject(); } }
- 给模型属性绑定转换器
修改Root类,给attributes属性加上转换器特性:
public class Root { [JsonConverter(typeof(SimpleTypeDictionaryConverter))] public IDictionary<string, object> attributes { get; set; } }
- 测试效果
重新运行原测试代码,此时o.attributes["value1"].GetType()会输出System.String,数值类型的value2会被转为System.Double,null值也能正确识别。
额外说明
- 如果想把整数单独转成
long而非统一用double,可以在处理数值类型时先判断reader.TryGetInt64(out long intValue),优先转整数,再处理浮点数。 - 上述转换器仅处理了你提到的三种类型,若有其他类型需求,直接扩展
switch分支即可。
内容的提问来源于stack exchange,提问作者Berend
相关产品推荐
相关产品推荐

