使用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
相关产品推荐
相关产品推荐

