.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); } }
使用转换器有两种方式:
- 直接在
value属性上标记特性:
public class MetadataAttribute { // ...其他属性 [JsonConverter(typeof(IntToStringConverter))] public string value { get; set; } // ...其他属性 }
- 反序列化时传入配置选项:
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
相关产品推荐
相关产品推荐

