在反序列化的JSON.NET对象

时间:2018-03-27 15:22:05

标签: c# json json.net deserialization

这基本上是问题Newtonsoft Object → Get JSON string的后续内容。

我有一个看起来像这样的对象:

[JsonConverter(typeof(MessageConverter))]
public class Message
{
    public Message(string original)
    {
        this.Original = original;
    }

    public string Type { get; set; }

    public string Original { get; set; }
}

我的要求是在初始化时将原始JSON字符串存储为对象的一部分。我已经能够(部分)使用自定义JsonConverter成功实现此功能,然后基本上在JsonConverter执行此类操作:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    if (reader.TokenType == Newtonsoft.Json.JsonToken.Null)
        return null;

    JObject obj = JObject.Load(reader);
    return new Message(obj.ToString(Formatting.None))
    {
        Type = obj["type"].ToString()
    };
}

然而,我遇到的问题是当我尝试从Message继承类似

之类的东西时
public class CustomMessage : Message
{
    public string Prop1 { get; set; }
}

由于显而易见的原因,我的代码失败了,因为它尝试返回新的Message()而不是新的CustomMessage()

没有用我的所有子类型实现一个大的if语句,并使用类似JObject["prop"].ToObject<T>()之类的东西手动绑定,如何在仍使用所有子类型值绑定的同时成功填充Original属性默认的反序列化?

注意:执行此操作的原因是因为原始邮件可能包含实际上未绑定的数据,因此我无法添加将对象序列化为的属性它代表着。

2 个答案:

答案 0 :(得分:1)

以下解决方案

您可以做的一件事是按通用JsonConverter属性装饰每个子类。

[JsonConverter(typeof(MessageConverter<Message>))]
public class Message
{
    public Message(string original)
    {
        this.Original = original;
    }

    public string Type { get; set; }

    public string Original { get; set; }
}
[JsonConverter(typeof(MessageConverter<CustomMessage>))]
public class CustomMessage : Message
{
    public CustomMessage(string original) : base(original)
    {
    }
    public string Prop1 { get; set; }
}

public class MessageConverter:JsonConverter其中T:Message     {         public override void WriteJson(JsonWriter writer,object value,JsonSerializer serializer)         {             throw new NotImplementedException();         }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == Newtonsoft.Json.JsonToken.Null)
            return null;

        JObject obj = JObject.Load(reader);
        var customObject = JsonConvert.DeserializeObject<T>(obj.ToString(), new JsonSerializerSettings 
                        {
                            ContractResolver = new CustomContractResolver()
                        });
        customObject.Original = obj.ToString();
            return customObject;
    }

    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }
}

//This will remove our declared Converter
public class CustomContractResolver : DefaultContractResolver
{
    protected override JsonConverter ResolveContractConverter (Type objectType)
    {
        return null;
    }
}

然后您可以为所有子类使用相同的序列化程序

CustomMessage x = JsonConvert.DeserializeObject<CustomMessage>("{\"type\":\"Test\",\"Prop1\":\"Prop1\"}");
 Message y = JsonConvert.DeserializeObject<Message>("{\"type\":\"Test\"}");

这是输出屏幕截图 enter image description here

答案 1 :(得分:1)

我打开这个问题,希望有人提出更好的答案,但我暂时使用以下解决方案来解决我的问题。

public static class MessageExtensions
{
    public static T Deserialize<T>(this string message) where T : Message
    {
        T instance = Activator.CreateInstance<T>();
        instance.Original = message;
        JsonConvert.PopulateObject(message, instance);
        return instance;
    }
}