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

C# Newtonsoft如何将含多类型值的JSON数组转换为实体类

多类型值JSON结构映射方案

问题根源

你当前的实体定义和转换逻辑存在两个核心问题:

  • 不能在同一个类的多个属性上标记指向同一JSON字段的[JsonProperty("value")]特性,序列化器处理时会出现属性覆盖,最终只有最后一个声明的属性能正常赋值
  • 自定义JsonConverter时没有先判断value字段的实际Token类型做分支处理,只会按固定类型解析,自然无法适配数字、字符串、对象三种完全不同的值结构

实现步骤

1. 修正实体类定义

移除三个值属性上重复的[JsonProperty("value")]标记,避免映射冲突:

public class RandomProperties
{
    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonIgnore]
    public int? ValueInt { get; set; }
    
    [JsonIgnore]
    public string ValueString { get; set; }

    [JsonIgnore]
    public ValueObject ValueObject { get; set; }
}

public class ValueObject
{
    [JsonProperty("type")]
    public string Type { get; set; }

    [JsonProperty("currency")]
    public string Currency { get; set; }

    [JsonProperty("amount")]
    public int? Amount { get; set; }

    [JsonProperty("typeId")]
    public string TypeId { get; set; }

    [JsonProperty("id")]
    public string ValueId { get; set; }
}

2. 编写针对RandomProperties的自定义类型转换器

转换器核心逻辑是读取JSON片段后,先判断value字段的Token类型,再按对应类型解析赋值:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class RandomPropertiesConverter : JsonConverter<RandomProperties>
{
    public override RandomProperties ReadJson(JsonReader reader, Type objectType, RandomProperties existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        JObject rawObj = JObject.Load(reader);
        RandomProperties result = new RandomProperties
        {
            Name = rawObj.Value<string>("name")
        };

        JToken valueToken = rawObj["value"];
        switch (valueToken.Type)
        {
            case JTokenType.Integer:
                result.ValueInt = valueToken.Value<int>();
                break;
            case JTokenType.String:
                result.ValueString = valueToken.Value<string>();
                break;
            case JTokenType.Object:
                result.ValueObject = valueToken.ToObject<ValueObject>(serializer);
                break;
            // 可按需扩展浮点数、布尔值等其他类型的处理分支
        }
        return result;
    }

    public override void WriteJson(JsonWriter writer, RandomProperties value, JsonSerializer serializer)
    {
        JObject outputObj = new JObject
        {
            ["name"] = value.Name
        };

        // 序列化时优先输出非空的value值
        if (value.ValueInt.HasValue)
        {
            outputObj["value"] = value.ValueInt.Value;
        }
        else if (!string.IsNullOrEmpty(value.ValueString))
        {
            outputObj["value"] = value.ValueString;
        }
        else if (value.ValueObject != null)
        {
            outputObj["value"] = JObject.FromObject(value.ValueObject, serializer);
        }

        outputObj.WriteTo(writer);
    }
}

3. 注册转换器

在RandomProperties类上标记转换器特性即可生效:

[JsonConverter(typeof(RandomPropertiesConverter))]
public class RandomProperties
{
    // 类定义和之前保持一致
}

补充说明

如果你使用的是System.Text.Json,核心逻辑完全一致,只需要把解析逻辑从Newtonsoft的JObject换成System.Text.Json的JsonDocument即可,不需要调整分支判断的思路。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 15:48:15