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

将UPS API RatingResponse反序列化为C#强类型对象的问题

解决UPS REST API RatedPackage反序列化问题的几种方案

针对UPS API返回的RatedPackage可能是单个对象或数组的情况,以下是几种直接可行的处理方式:

方案一:使用Json.NET自定义转换器(推荐)

如果项目使用Newtonsoft.Json(Json.NET),可以编写通用转换器自动将单个对象转为数组:

public class SingleOrArrayConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(List<T>) || objectType == typeof(T[]);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.Load(reader);
        if (token.Type == JTokenType.Array)
        {
            return token.ToObject(objectType, serializer);
        }
        // 单个对象时包装成数组/列表
        var list = Activator.CreateInstance(objectType) as IList;
        var item = token.ToObject<T>(serializer);
        list.Add(item);
        return list;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}

接着在RatingResponse模型的RatedPackage属性上标记转换器:

public class RatingResponse
{
    // 其他属性...
    [JsonConverter(typeof(SingleOrArrayConverter<RatedPackage>))]
    public RatedPackage[] RatedPackages { get; set; }
}

这样无论API返回单个对象还是数组,都能正确反序列化为数组类型。

方案二:使用System.Text.Json自定义转换器(.NET Core/.NET 5+)

如果使用内置的System.Text.Json,可编写对应转换器:

public class SingleOrArrayConverter<T> : JsonConverter<T[]>
{
    public override T[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType == JsonTokenType.StartObject)
        {
            var item = JsonSerializer.Deserialize<T>(ref reader, options);
            return new[] { item };
        }
        else if (reader.TokenType == JsonTokenType.StartArray)
        {
            return JsonSerializer.Deserialize<T[]>(ref reader, options);
        }
        throw new JsonException("Expected object or array");
    }

    public override void Write(Utf8JsonWriter writer, T[] value, JsonSerializerOptions options)
    {
        JsonSerializer.Serialize(writer, value, options);
    }
}

然后在模型属性上配置:

public class RatingResponse
{
    // 其他属性...
    [JsonConverter(typeof(SingleOrArrayConverter<RatedPackage>))]
    public RatedPackage[] RatedPackages { get; set; }
}

方案三:先反序列化为动态类型再转换

若不想编写转换器,可先将响应反序列化为动态类型,手动判断RatedPackage类型后转换:

Json.NET版本:

var responseJson = await httpResponse.Content.ReadAsStringAsync();
var jObject = JObject.Parse(responseJson);
var ratedPackageToken = jObject["RatedShipment"]["RatedPackage"];

RatedPackage[] ratedPackages;
if (ratedPackageToken.Type == JTokenType.Array)
{
    ratedPackages = ratedPackageToken.ToObject<RatedPackage[]>();
}
else
{
    ratedPackages = new[] { ratedPackageToken.ToObject<RatedPackage>() };
}

// 映射其他属性到RatingResponse
var ratingResponse = jObject.ToObject<RatingResponse>();
ratingResponse.RatedPackages = ratedPackages;

System.Text.Json版本:

var responseJson = await httpResponse.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(responseJson);
var root = doc.RootElement;
var ratedPackageElement = root.GetProperty("RatedShipment").GetProperty("RatedPackage");

RatedPackage[] ratedPackages;
if (ratedPackageElement.ValueKind == JsonValueKind.Array)
{
    ratedPackages = JsonSerializer.Deserialize<RatedPackage[]>(ratedPackageElement);
}
else
{
    var singlePackage = JsonSerializer.Deserialize<RatedPackage>(ratedPackageElement);
    ratedPackages = new[] { singlePackage };
}

// 映射到RatingResponse
var ratingResponse = JsonSerializer.Deserialize<RatingResponse>(responseJson);
ratingResponse.RatedPackages = ratedPackages;

这种方式适合临时处理,但通用性不如自定义转换器。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 12:05:19