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

如何在返回类型不确定时调用FlurlHttpException.GetResponseJsonAsync?

关于FlurlHttpException.GetResponseJsonAsync类型不匹配的行为与兼容处理

类型不匹配时的行为

当调用ex.GetResponseJsonAsync<ErrorA>()但实际返回的是ErrorB的JSON结构时,默认会抛出反序列化异常:

  • 若使用Flurl默认的Newtonsoft.Json序列化器,会抛出JsonSerializationException
  • 若配置为System.Text.Json,则抛出JsonException

不会自动生成带有默认属性的ErrorA对象,因为默认的反序列化规则要求JSON结构与目标类型匹配——比如ErrorB中不存在ErrorA的必填字段,或字段类型不匹配时,反序列化器会直接报错,而非填充默认值(除非你手动配置了序列化器的容错选项,比如忽略缺失属性、允许类型不匹配等,但这不是默认行为)。

兼容两种错误类型的处理方案

针对同一错误码可能返回两种不同错误结构的场景,推荐以下几种可靠的处理方式:

方案1:先读取原始JSON,判断结构后再反序列化

先将响应内容读取为字符串,解析成JObject(Newtonsoft)或JsonElement(System.Text.Json),通过特征字段判断实际类型:

// 先获取原始JSON字符串
var json = await ex.GetResponseStringAsync();
// 用Newtonsoft.Json解析
var jObj = JObject.Parse(json);

ErrorBase error;
// 根据特征字段区分类型(比如ErrorA有ErrorACode,ErrorB有ErrorBCode)
if (jObj.ContainsKey("ErrorACode"))
{
    error = jObj.ToObject<ErrorA>();
}
else if (jObj.ContainsKey("ErrorBCode"))
{
    error = jObj.ToObject<ErrorB>();
}
else
{
    throw new InvalidOperationException("未知的错误响应格式");
}

建议让ErrorA和ErrorB继承同一个基类ErrorBase,方便后续统一处理错误逻辑。

方案2:尝试反序列化第一种类型,失败则 fallback 到第二种

先尝试反序列化为ErrorA,捕获反序列化异常后再尝试ErrorB。注意要先读取JSON字符串,避免重复读取响应流导致的错误:

var json = await ex.GetResponseStringAsync();
ErrorBase error;

try
{
    // Newtonsoft.Json
    error = JsonConvert.DeserializeObject<ErrorA>(json);
    // 若用System.Text.Json则替换为:
    // error = JsonSerializer.Deserialize<ErrorA>(json);
}
catch (JsonSerializationException) // System.Text.Json用JsonException
{
    try
    {
        error = JsonConvert.DeserializeObject<ErrorB>(json);
    }
    catch (JsonSerializationException)
    {
        throw new InvalidOperationException("无法解析错误响应格式");
    }
}

方案3:定义包含所有字段的联合类型

如果两种错误类型的字段无冲突,可以定义一个包含所有可能字段的联合类,反序列化后通过字段是否有值判断类型:

public class ErrorUnion
{
    // ErrorA的字段
    public string ErrorACode { get; set; }
    public string ErrorAMessage { get; set; }
    // ErrorB的字段
    public int ErrorBCode { get; set; }
    public string ErrorBDetails { get; set; }
}

// 使用时
var errorUnion = await ex.GetResponseJsonAsync<ErrorUnion>();
if (!string.IsNullOrEmpty(errorUnion.ErrorACode))
{
    // 按ErrorA逻辑处理
}
else if (errorUnion.ErrorBCode != 0)
{
    // 按ErrorB逻辑处理
}

这种方式实现简单,但当字段较多或有冲突时不适用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 03:40:31