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

如何用Newtonsoft.Json根据属性反序列化不同JSON到对应对象

解决方案

首先需要补全对应的数据结构类:

// 对应第一种JSON格式的结构
public class Structure1
{
    public int Id { get; set; }
    public string Result { get; set; }
    public string Comment { get; set; }
}

// 对应第二种JSON格式的结构
public class Structure2
{
    public int UserId { get; set; }
    public string PhoneNumber { get; set; }
    public string Message { get; set; }
}

// 你定义的信封类
public class EnvelopeObject
{
    public Structure1 Structure1 { get; set; }
    public Structure2 Structure2 { get; set; }
}

方法一:简便尝试法(无需自定义转换器)

直接尝试将JSON依次反序列化为Structure1和Structure2,成功的那个存入EnvelopeObject,失败则跳过。这种方式代码简单,适合格式差异明显的场景:

使用 Newtonsoft.Json(Json.NET)

public static EnvelopeObject DeserializeToEnvelope(string json)
{
    var envelope = new EnvelopeObject();
    
    // 尝试反序列为Structure1
    try
    {
        var structure1 = JsonConvert.DeserializeObject<Structure1>(json);
        // 验证是否真的匹配(避免空值或默认值导致误判)
        if (structure1.Id != 0 || !string.IsNullOrEmpty(structure1.Result))
        {
            envelope.Structure1 = structure1;
            return envelope;
        }
    }
    catch (JsonSerializationException)
    {
        // 反序列失败,继续尝试Structure2
    }

    // 尝试反序列为Structure2
    try
    {
        envelope.Structure2 = JsonConvert.DeserializeObject<Structure2>(json);
        return envelope;
    }
    catch (JsonSerializationException)
    {
        throw new InvalidOperationException("JSON格式不匹配Structure1或Structure2");
    }
}

方法二:自定义转换器(更优雅、性能更好)

通过自定义JSON转换器,直接解析JSON结构,判断属于哪种格式后再反序列化,适合复杂场景或高并发场景。

使用 Newtonsoft.Json 实现自定义转换器

public class EnvelopeObjectConverter : JsonConverter<EnvelopeObject>
{
    public override EnvelopeObject ReadJson(JsonReader reader, Type objectType, EnvelopeObject existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var jsonObj = JObject.Load(reader);
        var envelope = new EnvelopeObject();

        // 通过特征字段判断格式(比如Id是Structure1的独有字段)
        if (jsonObj.ContainsKey("Id"))
        {
            envelope.Structure1 = jsonObj.ToObject<Structure1>(serializer);
        }
        // 通过UserId判断是Structure2的格式
        else if (jsonObj.ContainsKey("UserId"))
        {
            envelope.Structure2 = jsonObj.ToObject<Structure2>(serializer);
        }
        else
        {
            throw new JsonSerializationException("无法识别的JSON格式");
        }

        return envelope;
    }

    public override void WriteJson(JsonWriter writer, EnvelopeObject value, JsonSerializer serializer)
    {
        // 序列化时只输出有值的结构
        if (value.Structure1 != null)
        {
            serializer.Serialize(writer, value.Structure1);
        }
        else if (value.Structure2 != null)
        {
            serializer.Serialize(writer, value.Structure2);
        }
        else
        {
            writer.WriteNull();
        }
    }
}

使用转换器的两种方式:

  1. 给EnvelopeObject添加特性:
[JsonConverter(typeof(EnvelopeObjectConverter))]
public class EnvelopeObject
{
    public Structure1 Structure1 { get; set; }
    public Structure2 Structure2 { get; set; }
}

// 反序列化时直接调用
var envelope = JsonConvert.DeserializeObject<EnvelopeObject>(json);
  1. 序列化时手动指定转换器:
var settings = new JsonSerializerSettings();
settings.Converters.Add(new EnvelopeObjectConverter());
var envelope = JsonConvert.DeserializeObject<EnvelopeObject>(json, settings);

使用 System.Text.Json 实现自定义转换器

如果使用.NET Core/.NET 5+自带的System.Text.Json,转换器实现如下:

public class EnvelopeObjectConverter : JsonConverter<EnvelopeObject>
{
    public override EnvelopeObject Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using var doc = JsonDocument.ParseValue(ref reader);
        var root = doc.RootElement;
        var envelope = new EnvelopeObject();

        if (root.TryGetProperty("Id", out _))
        {
            envelope.Structure1 = JsonSerializer.Deserialize<Structure1>(root.GetRawText(), options);
        }
        else if (root.TryGetProperty("UserId", out _))
        {
            envelope.Structure2 = JsonSerializer.Deserialize<Structure2>(root.GetRawText(), options);
        }
        else
        {
            throw new JsonException("无法识别的JSON格式");
        }

        return envelope;
    }

    public override void Write(Utf8JsonWriter writer, EnvelopeObject value, JsonSerializerOptions options)
    {
        if (value.Structure1 != null)
        {
            JsonSerializer.Serialize(writer, value.Structure1, options);
        }
        else if (value.Structure2 != null)
        {
            JsonSerializer.Serialize(writer, value.Structure2, options);
        }
        else
        {
            writer.WriteNullValue();
        }
    }
}

使用方式:

var options = new JsonSerializerOptions();
options.Converters.Add(new EnvelopeObjectConverter());
var envelope = JsonSerializer.Deserialize<EnvelopeObject>(json, options);

两种方法对比

  • 简便尝试法:代码量少,无需额外定义转换器;缺点是依赖异常捕获,性能略低,若两种结构有重叠字段可能出现误判。
  • 自定义转换器:性能更优,判断逻辑精准,适合复杂场景或高并发场景;代码量稍多,但扩展性更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 01:35:19