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

JsonSerializer反序列化:源属性全为数组但目标非数组如何处理

适配全数组包装JSON的反序列化方案

问题说明

输入JSON的所有属性值都被包装为数组格式,无论目标属性实际是单值还是数组类型,示例JSON:

{
   "StringValue": ["mystringvalue"],
   "StringArrayValue": ["value1","value2"],
   "LongValue": [123]
}

目标接收类定义:

class MyClass {
   public string StringValue {get;set;}
   public string[] StringArrayValue {get;set;}
   public long LongValue {get;set;}
}

默认System.Text.Json反序列化会抛出类型不匹配异常,因为无法直接将JSON数组转换为非数组的CLR类型,需要自定义转换逻辑实现:目标属性为非数组类型时,自动读取对应JSON数组的第一个元素赋值;目标属性为数组类型时,正常读取全部数组元素完成反序列化。

实现步骤

1. 编写通用转换器

实现JsonConverterFactory做全局类型适配,不需要为每个属性单独打特性,所有非数组类型自动走取数组首元素的逻辑:

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

public class ArrayWrappedValueConverter : JsonConverterFactory
{
    public override bool CanConvert(Type typeToConvert)
    {
        // 数组类型走默认反序列化逻辑,不拦截
        return !typeToConvert.IsArray;
    }

    public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
    {
        var innerConverterType = typeof(InnerArrayConverter<>).MakeGenericType(typeToConvert);
        return (JsonConverter)Activator.CreateInstance(innerConverterType)!;
    }

    private class InnerArrayConverter<T> : JsonConverter<T>
    {
        public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType != JsonTokenType.StartArray)
                throw new JsonException($"当前值不是数组格式,无法转换为{typeof(T).Name}类型");
            
            reader.Read();
            // 取数组第一个元素反序列化为目标类型
            var result = JsonSerializer.Deserialize<T>(ref reader, options);
            
            // 跳过数组内剩余元素直到数组结束
            while (reader.Read())
            {
                if (reader.TokenType == JsonTokenType.EndArray) break;
                reader.Skip();
            }

            return result!;
        }

        public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
        {
            // 序列化时默认包装为数组,和输入格式对齐
            writer.WriteStartArray();
            JsonSerializer.Serialize(writer, value, options);
            writer.WriteEndArray();
        }
    }
}

如果仅需要处理反序列化场景,不需要序列化输出和输入格式保持一致,可直接将Write方法实现改为抛出NotSupportedException,或者直接写入单值不做数组包装。

2. 配置反序列化选项

将转换器加入JsonSerializerOptions,反序列化时传入即可:

var jsonOptions = new JsonSerializerOptions
{
    Converters = { new ArrayWrappedValueConverter() },
    PropertyNameCaseInsensitive = true // 按需开启属性名大小写不敏感匹配
};

// 执行反序列化
MyClass instance = JsonSerializer.Deserialize<MyClass>(jsonContent, jsonOptions);

效果验证

反序列化后得到的实例:

  • StringValue 赋值为数组首元素 "mystringvalue"
  • StringArrayValue 正常拿到完整数组 ["value1", "value2"]
  • LongValue 赋值为数组首元素 123

如果你用的是Newtonsoft.Json,实现逻辑完全一致,只需要继承对应框架的JsonConverter基类实现读取逻辑、加入序列化配置即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 04:45:38