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

.NET内置JSON反序列化:处理value字段的字符串/整数歧义问题

问题描述

需要用.NET内置的JsonSerializer反序列化包含如下结构的JSON数组:

"attributes": [
{
    "trait_type": "Subseries",
    "value": "Templar Order"
},
{
    "trait_type": "Colorfulness",
    "value": 2,
    "min_value": 1,
    "max_value": 5
},
{
    "trait_type": "Style",
    "value": "CGI"
},
{
    "trait_type": "Material",
    "value": "Steel"
},
{
    "trait_type": "Special Effects",
    "value": "Rare"
},
{
    "trait_type": "Background",
    "value": "Rare"
}]

每个attribute对象包含必填的trait_type和value字段,其中value可以是字符串或整数类型;min_value和max_value为可选整数字段。

已定义MetadataAttribute类,但反序列化时,JSON中的整数类型value无法自动转换为类中的string类型value属性:

public class MetadataAttribute
{
    public MetadataAttribute(string Trait_Type, string Value)
    {
        trait_type = Trait_Type;
        value = Value;
    }
    public MetadataAttribute(string Trait_Type, int Value, int? Min_Value = null, int? Max_Value = null)
    {
        trait_type = Trait_Type;
        value = Value.ToString();
        min_value = Min_Value;
        max_value = Max_Value;
    }
    public MetadataAttribute() { }
    /// <summary>
    ///  the attribute name, eg sharpness
    /// </summary>
    public string trait_type { get; set; }
    /// <summary>
    /// the value of the attribute, eg 10
    /// </summary>
    public string value { get; set; }
    /// <summary>
    /// optional: the minimum value atribute to provide a possible range
    /// </summary>
    public int? min_value{get;set;}
    /// <summary>
    /// optional: the maximum value attribute to provide a possible range
    /// </summary>
    public int? max_value { get; set; }
}

当前反序列化代码仅在value全为字符串时正常工作:

public static Metadata Load(string path)
{
    FileInfo testFile = new FileInfo(path);
    string text = File.ReadAllText(testFile.FullName);
    Metadata json = JsonSerializer.Deserialize<Metadata>(text);
    return json;
}
解决方案

有两种常用方法解决这个类型歧义问题:

方法一:自定义JSON转换器

创建一个继承自JsonConverter<string>的转换器,专门处理整数到字符串的转换逻辑:

public class IntToStringConverter : JsonConverter<string>
{
    public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType == JsonTokenType.Number)
        {
            return reader.GetInt32().ToString();
        }
        else if (reader.TokenType == JsonTokenType.String)
        {
            return reader.GetString();
        }
        throw new JsonException("Unexpected token type for value property.");
    }

    public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value);
    }
}

使用转换器有两种方式:

  1. 直接在value属性上标记特性:
public class MetadataAttribute
{
    // ...其他属性
    [JsonConverter(typeof(IntToStringConverter))]
    public string value { get; set; }
    // ...其他属性
}
  1. 反序列化时传入配置选项:
public static Metadata Load(string path)
{
    FileInfo testFile = new FileInfo(path);
    string text = File.ReadAllText(testFile.FullName);
    var options = new JsonSerializerOptions();
    options.Converters.Add(new IntToStringConverter());
    Metadata json = JsonSerializer.Deserialize<Metadata>(text, options);
    return json;
}

方法二:用object类型中转转换

修改MetadataAttribute类的value属性,先用object类型接收JSON中的值,再通过属性的getter自动转换为字符串:

public class MetadataAttribute
{
    // ...其他构造函数和属性
    private object _value;
    public string value
    {
        get => _value?.ToString();
        set => _value = value;
    }
    // ...其他属性
}

这种方法无需额外编写转换器,适合简单场景;如果JSON中value可能出现布尔等其他类型,需要在getter中添加对应处理逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 02:41:58