使用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); } }
注册转换器有两种方式:
- 在
SerialNo类上标记特性:
[JsonConverter(typeof(SerialNoConverter))] public class SerialNo { // 原构造函数和属性逻辑保持不变 }
- 在序列化选项中添加转换器:
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
相关产品推荐
相关产品推荐

