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

使用System.Text.Json反序列化时,如何为属性设置多类型支持?

在C#模型中定义支持字符串或整数数组的属性约束

我希望模型中的values属性既能接收整数数组,也能接收字符串类型,请问在C#里该怎么正确定义这个约束?目前我的C#模型代码如下:

using System.Text.Json.Serialization;

public class TestClass
{
    // 这个字段只能是字符串或数组,不能是其他类型
    [JsonPropertyName("values")]
    public string? values { get; set; } = null; 
}

作为参考,Python中可以这样实现让values支持List[int]或str类型:

from pydantic import BaseModel, Field
from typing import List

class TestClass(BaseModel):
    values: List[int] | str = Field(None, alias="values")

解决方案:自定义Json转换器

C#的System.Text.Json默认不直接支持联合类型的序列化/反序列化,我们可以通过自定义JsonConverter来实现这个需求,同时保证类型校验的严谨性。

步骤1:定义封装类型(可选但更安全)

先创建一个专门的类来封装字符串或整数数组的结果,使用时能更清晰地判断当前值的类型:

public class StringOrIntArray
{
    public string? StringValue { get; set; }
    public int[]? IntArrayValue { get; set; }
    // 判断当前值是否为字符串
    public bool IsString => StringValue != null;
    // 判断当前值是否为整数数组
    public bool IsIntArray => IntArrayValue != null;
}

步骤2:实现自定义Json转换器

创建转换器处理两种类型的序列化和反序列化逻辑,遇到不符合要求的类型时直接抛出异常:

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

public class StringOrIntArrayConverter : JsonConverter<StringOrIntArray>
{
    public override StringOrIntArray? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        switch (reader.TokenType)
        {
            // 处理字符串类型
            case JsonTokenType.String:
                return new StringOrIntArray { StringValue = reader.GetString() };
            // 处理整数数组类型
            case JsonTokenType.StartArray:
                var intArray = JsonSerializer.Deserialize<int[]>(ref reader, options);
                return new StringOrIntArray { IntArrayValue = intArray };
            // 其他类型直接抛出异常
            default:
                throw new JsonException("values属性只能是字符串或整数数组");
        }
    }

    public override void Write(Utf8JsonWriter writer, StringOrIntArray value, JsonSerializerOptions options)
    {
        if (value.IsString)
        {
            JsonSerializer.Serialize(writer, value.StringValue, options);
        }
        else if (value.IsIntArray)
        {
            JsonSerializer.Serialize(writer, value.IntArrayValue, options);
        }
        else
        {
            throw new JsonException("没有可序列化的有效值");
        }
    }
}

步骤3:修改原模型类

在模型的values属性上添加转换器标记,替换原有的字符串类型:

using System.Text.Json.Serialization;

public class TestClass
{
    [JsonPropertyName("values")]
    [JsonConverter(typeof(StringOrIntArrayConverter))]
    public StringOrIntArray? Values { get; set; } = null;
}

使用示例

// 反序列化字符串类型的values
var json1 = "{\"values\": \"test string\"}";
var model1 = JsonSerializer.Deserialize<TestClass>(json1);
if (model1?.Values?.IsString == true)
{
    Console.WriteLine(model1.Values.StringValue); // 输出 "test string"
}

// 反序列化整数数组类型的values
var json2 = "{\"values\": [1, 2, 3]}";
var model2 = JsonSerializer.Deserialize<TestClass>(json2);
if (model2?.Values?.IsIntArray == true)
{
    Console.WriteLine(string.Join(", ", model2.Values.IntArrayValue)); // 输出 "1, 2, 3"
}

// 反序列化其他类型会抛出异常
var json3 = "{\"values\": 123}";
try
{
    var model3 = JsonSerializer.Deserialize<TestClass>(json3);
}
catch (JsonException ex)
{
    Console.WriteLine(ex.Message); // 输出 "values属性只能是字符串或整数数组"
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 07:53:14