You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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这类简单类型,就得自己写转换器处理。

具体步骤

  1. 编写自定义字典转换器
    这个转换器会逐个处理字典里的键值对,根据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();
    }
}
  1. 给模型属性绑定转换器
    修改Root类,给attributes属性加上转换器特性:
public class Root 
{
    [JsonConverter(typeof(SimpleTypeDictionaryConverter))]
    public IDictionary<string, object> attributes { get; set; } 
}
  1. 测试效果
    重新运行原测试代码,此时o.attributes["value1"].GetType()会输出System.String,数值类型的value2会被转为System.Double,null值也能正确识别。

额外说明

  • 如果想把整数单独转成long而非统一用double,可以在处理数值类型时先判断reader.TryGetInt64(out long intValue),优先转整数,再处理浮点数。
  • 上述转换器仅处理了你提到的三种类型,若有其他类型需求,直接扩展switch分支即可。

内容的提问来源于stack exchange,提问作者Berend

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 14:37:51