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

System.Text.Json反序列化:处理属性类型不一致并配置回退逻辑

处理System.Text.Json反序列化时的多类型属性回退问题

问题场景

调用外部API返回列表时,列表项的location属性可能是字符串,也可能是对象。需要把对象转成Location实例,字符串则把该属性设为null,同时不能抛出System.Text.Json.JsonException异常。

相关代码定义:

public class ListItem 
{
    [JsonPropertyName("location")]
    public Location Location { get;set; }
}

public class Location
{
    [JsonPropertyName("city")]
    public string City { get; set; }

    [JsonPropertyName("country")]
    public string Country { get; set; }
}

API返回示例:

[
  {
     "location": "some location",
     // 其他属性...
  },
  {
     "location": {
            "city": "some city",
            "country": "some country"
        }
  }
]

解决方案:自定义Json转换器

核心思路是给Location类型写一个自定义转换器,在反序列化时判断JSON token的类型,根据类型决定返回Location实例还是null。

自定义转换器代码

using System.Text.Json;
using System.Text.Json.Serialization;

public class LocationConverter : JsonConverter<Location>
{
    public override Location Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // 检查当前JSON的token类型
        if (reader.TokenType == JsonTokenType.String)
        {
            // 跳过字符串值,直接返回null
            reader.Skip();
            return null;
        }
        else if (reader.TokenType == JsonTokenType.StartObject)
        {
            // 正常反序列化为Location对象
            return JsonSerializer.Deserialize<Location>(ref reader, options);
        }
        // 其他类型(比如数字、数组)也返回null,按需调整
        reader.Skip();
        return null;
    }

    public override void Write(Utf8JsonWriter writer, Location value, JsonSerializerOptions options)
    {
        // 如果不需要序列化Location对象,这里可以抛出NotImplementedException
        JsonSerializer.Serialize(writer, value, options);
    }
}

应用转换器的两种方式

方式1:属性标记

直接在ListItem的Location属性上加特性,只对这个属性生效:

public class ListItem 
{
    [JsonPropertyName("location")]
    [JsonConverter(typeof(LocationConverter))]
    public Location Location { get;set; }
}

然后正常反序列化:

var jsonStr = "API返回的JSON字符串";
var itemList = JsonSerializer.Deserialize<List<ListItem>>(jsonStr);

方式2:全局配置

如果多个地方都要处理Location类型,可以全局添加转换器:

var serializeOptions = new JsonSerializerOptions();
serializeOptions.Converters.Add(new LocationConverter());

var jsonStr = "API返回的JSON字符串";
var itemList = JsonSerializer.Deserialize<List<ListItem>>(jsonStr, serializeOptions);

这样处理后,遇到location是字符串时,ListItem.Location会被设为null;是对象时则正常转成Location实例,不会抛出异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 16:15:40