使用 System.Text.Json 反序列化 json 时允许一个属性有多种类型

问题描述 投票:0回答:1

我期望传入数据中的特定属性是整数数组或字符串。在我的模型中定义此条件的正确方法是什么?

using System.Text.Json.Serialization;

public class TestClass
{
    // this field should either be a string or an array. Nothing else
    [JsonPropertyName("values")
    public string? values { get; set; } = null; 
}

作为参考,在Python中,我可以这样做,并且可以将我的values属性设置为字符串或int列表:

from pydantic import BaseModel, Field
from typing import List

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

提前谢谢您

c# serialization types system.text.json
1个回答
0
投票

C# 不支持具有多种(数据)类型的属性。对于您的情况,我建议使用两个属性来存储不同类型的值。

values
属性与
JsonElement
类型一起应用,以允许接受动态 JSON(类型)值,以便稍后可以将其反序列化为指定类型。

方法一:使用getter反序列化

public class TestClass
{
    [JsonInclude]
    [JsonPropertyName("values")]
    public JsonElement? values { get; set; } = null; //this field should either be a string or an array.  nothing else.
    
    [JsonIgnore]
    public string StringValue 
    { 
        get
        {
            if (values.HasValue && values.Value.ValueKind == JsonValueKind.String)
            {
                return values.Value.ToString();
            }
            
            return null;
        }       
    }
    
    [JsonIgnore]
    public int[] IntegerValues
    { 
        get
        {
            if (values.HasValue && values.Value.ValueKind == JsonValueKind.Array)
            {
                try
                {
                    return values.Value.Deserialize<int[]>();
                }
                catch
                {
                    return null;    
                }
            }
            
            return null;
        }
    }
}

方法 2:实施

JsonConverter

public class TestClassConverter : JsonConverter<TestClass>
{
    public override TestClass Read(
        ref Utf8JsonReader reader,
        Type typeToConvert,
        JsonSerializerOptions options)
        {
            TestClass value = new TestClass();

            JsonElement root = JsonElement.ParseValue(ref reader);
            JsonElement values = root.GetProperty("values");

            value.values = values;

            switch (values.ValueKind)
            {
                case JsonValueKind.String:
                    value.StringValue = values.ToString();
                    break;

                case JsonValueKind.Array:
                    value.IntegerValues = JsonSerializer.Deserialize<int[]>(values);
                    break;

                default:
                    throw new JsonException("Unsupported values type");
            }

            return value;
        }


    public override void Write(
        Utf8JsonWriter writer,
        TestClass value,
        JsonSerializerOptions options) =>
            throw new NotImplementedException();
}
[JsonConverter(typeof(TestClassConverter))]
public class TestClass
{
    [JsonInclude]
    [JsonPropertyName("values")]
    public JsonElement? values { get; set; } = null; //this field should either be a string or an array.  nothing else.
    
    [JsonIgnore]
    public string StringValue { get; set; }
    
    [JsonIgnore]
    public int[] IntegerValues { get; set; }
}
© www.soinside.com 2019 - 2024. All rights reserved.