为何使用XNamespace作为属性时无法反序列化类?
为什么使用XNamespace作为属性时无法反序列化类?
你遇到的问题是使用System.Text.Json反序列化包含XNamespace属性的类时失败,错误提示如下:
不支持对无无参构造函数、单一参数构造函数或未标注'JsonConstructorAttribute'的参数化构造函数的类型进行反序列化。类型为'System.Xml.Linq.XNamespace'。
问题原因
XNamespace的设计比较特殊:它没有无参构造函数,且接收字符串的单一参数构造函数未标记[JsonConstructor]特性。System.Text.Json默认无法识别JSON中{"NamespaceName": "..."}的结构,也不知道如何将其映射到XNamespace实例。而自定义类/值类型能正常工作,是因为你可以控制它们的构造函数或结构,让序列化器能够识别处理。
解决方案
方案1:自定义JsonConverter
创建一个XNamespace的转换器,明确告诉序列化器如何处理JSON与XNamespace的互转:
using System; using System.Text.Json; using System.Text.Json.Serialization; using System.Xml.Linq; public class XNamespaceConverter : JsonConverter<XNamespace> { public override XNamespace Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using var doc = JsonDocument.ParseValue(ref reader); var namespaceName = doc.RootElement.GetProperty("NamespaceName").GetString(); return XNamespace.Get(namespaceName); } public override void Write(Utf8JsonWriter writer, XNamespace value, JsonSerializerOptions options) { writer.WriteStartObject(); writer.WriteString("NamespaceName", value.NamespaceName); writer.WriteEndObject(); } }
使用转换器进行反序列化:
public class Program { public static void Main() { var x = @"{""NS"": {""NamespaceName"": ""http://www.some.ns/Enterprise""}}"; var options = new JsonSerializerOptions(); options.Converters.Add(new XNamespaceConverter()); var z = JsonSerializer.Deserialize<Some>(x, options); } } public class Some(XNamespace ns) { public XNamespace NS { get; set; } = ns; }
方案2:调整构造函数与JSON结构
如果可以修改JSON格式,直接传递命名空间字符串,并给类的构造函数添加[JsonConstructor]:
修改后的JSON:
{"NS": "http://www.some.ns/Enterprise"}
修改后的类:
public class Some { [JsonConstructor] public Some(XNamespace ns) { NS = ns; } public XNamespace NS { get; set; } }
此时System.Text.Json会通过标记的构造函数,直接将字符串转换为XNamespace实例。
方案3:中间属性过渡
添加一个中间属性接收JSON数据,再转换为XNamespace,无需修改原JSON结构:
public class Some { public XNamespace NS { get; set; } [JsonPropertyName("NS")] private NsWrapper NsWrapper { set => NS = XNamespace.Get(value.NamespaceName); } private class NsWrapper { public string NamespaceName { get; set; } } }
内容的提问来源于stack exchange,提问作者Post Impatica
相关产品推荐
相关产品推荐

