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

使用System.Text.Json构造函数反序列化SerialNo类失败,求解决

问题:System.Text.Json反序列化自定义类型失败,无法实例化SerialNo

我正在使用System.Text.Json进行反序列化操作,希望通过SerialNo(string serialNo)构造函数构建对象,相关代码如下:

public class SerialNo
{
    [JsonConstructor]
    public SerialNo(string serialNo)
    {
        if (serialNo == null) throw new ArgumentNullException(nameof(serialNo));

        if (string.IsNullOrWhiteSpace(serialNo)) throw new Exception("My exception text");

        Value = serialNo.Trim('0');
    }

    public string Value { get; set; }
}

public class Item
{
    public SerialNo SerialNo { get; set; }

    public string AffiliationOrgCode { get; set; }
}

public class Root
{
    public List<Item> Item { get; set; }
}

public class DeserializationTestsWithSystemTextJson
{
    private const string JsonString = @"
        {
            ""item"": [
              {
                ""serialNo"": ""000000000002200878"",
                ""affiliationOrgCode"": ""OrgCode1""
              },
              {
                ""serialNo"": ""000000000002201675"",
                ""affiliationOrgCode"": ""OrgCode1""
              }
            ]
        }
    ";

    [Fact]
    public void Simple_Deserialization_With_SystemTextJson()
    {
        var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);
        var deserializedClass = JsonSerializer.Deserialize<Root>(JsonString, options);

        Assert.NotNull(deserializedClass);
        Assert.Equal("2201675", deserializedClass.Item[1].SerialNo.Value);
    }
}

反序列化失败,报错信息如下:

The JSON value could not be converted to JsonNetDeserialization.Test.WithSystemText.SerialNo. Path: $.item[0].serialNo | LineNumber: 3 | BytePositionInLine: 44.


问题原因

System.Text.Json默认不支持直接将JSON字符串值反序列化为自定义引用类型(如SerialNo),即使该类型定义了匹配的单参数构造函数。它需要明确的类型转换逻辑来完成字符串到自定义对象的映射。

解决方法

方法一:实现自定义JSON转换器(推荐)

为SerialNo类编写JsonConverter<SerialNo>,手动处理字符串与SerialNo对象的转换逻辑:

public class SerialNoConverter : JsonConverter<SerialNo>
{
    public override SerialNo Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.String)
        {
            throw new JsonException("SerialNo必须是字符串类型");
        }
        string serialValue = reader.GetString();
        return new SerialNo(serialValue);
    }

    public override void Write(Utf8JsonWriter writer, SerialNo value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.Value);
    }
}

注册转换器有两种方式:

  1. 在SerialNo类上标记特性:
[JsonConverter(typeof(SerialNoConverter))]
public class SerialNo
{
    // 原构造函数和属性逻辑保持不变
}
  1. 在序列化选项中添加转换器:
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);
options.Converters.Add(new SerialNoConverter());
var deserializedClass = JsonSerializer.Deserialize<Root>(JsonString, options);

方法二:将SerialNo改为值类型(struct)

如果业务允许,将SerialNo从class改为struct,System.Text.Json会自动尝试用单参数构造函数反序列化值类型:

public struct SerialNo
{
    [JsonConstructor]
    public SerialNo(string serialNo)
    {
        if (serialNo == null) throw new ArgumentNullException(nameof(serialNo));
        if (string.IsNullOrWhiteSpace(serialNo)) throw new Exception("My exception text");
        Value = serialNo.Trim('0');
    }

    public string Value { get; set; }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 18:40:38