一尘不染

反序列化期间如何以编程方式选择构造函数?

c#

我想以System.Security.Claims.Claim以下方式反序列化序列化的对象:

{
    "Issuer" : "LOCAL AUTHORITY",
    "OriginalIssuer" : "LOCAL AUTHORITY",
    "Type" : "http://my.org/ws/2015/01/identity/claims/mytype",
    "Value" : "myvalue",
    "ValueType" : "http://www.w3.org/2001/XMLSchema#string"
}

我得到的是JsonSerializationException

找不到用于类型System.Security.Claims.Claim的构造函数。一个类应该具有一个默认构造函数,一个带有参数的构造函数或一个标有JsonConstructor属性的构造函数。

经过一番调查后,我终于理解了上面消息中的 一个 的含义:JSON解串器无法找到正确的构造函数,因为在Claim类型的情况下,
多个带有参数的构造函数 (尽管存在一个带有与上面的参数完全匹配的参数的构造函数)属性)。

有没有一种方法可以告诉反序列化器在不将JsonConstructor属性添加到该mscorlib类型的情况下选择哪个构造函数?

Daniel Halan 几年前用Json.NET的补丁解决了这个问题。有没有办法解决这些问题而无需修改Json.NET?


阅读 313

收藏
2020-05-19

共1个答案

一尘不染

如果无法向[JsonConstructor]目标类添加属性(因为您不拥有代码),则通常的解决方法是JsonConverter按照@James
Thorpe在注释中的建议创建自定义。这很简单。您可以将JSON加载到中JObject,然后从中选择各个属性以实例化Claim实例。这是您需要的代码:

class ClaimConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(System.Security.Claims.Claim));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        string type = (string)jo["Type"];
        string value = (string)jo["Value"];
        string valueType = (string)jo["ValueType"];
        string issuer = (string)jo["Issuer"];
        string originalIssuer = (string)jo["OriginalIssuer"];
        return new Claim(type, value, valueType, issuer, originalIssuer);
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

要使用转换器,只需将其实例传递给JsonConvert.DeserializeObject<T>()方法调用:

Claim claim = JsonConvert.DeserializeObject<Claim>(json, new ClaimConverter());

小提琴:https :
//dotnetfiddle.net/7LjgGR

2020-05-19