在反序列化的JSON.NET对象中存储原始JSON字符串

vjhs03f7  于 2023-02-17  发布在  .NET
关注(0)|答案(2)|浏览(179)

这基本上是问题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()
如果不使用JObject["prop"].ToObject<T>()之类的东西来实现一个包含所有子类型的大型if语句并手动绑定,那么如何在使用默认反序列化绑定所有子类型值的同时成功填充Original属性呢?

注意:这样做的原因是因为原始消息可能包含实际上未绑定的数据,所以我不能只添加一个属性来序列化对象。

7kqas0il

7kqas0il1#

以下解决方案有效
您可以做的一件事是用泛型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<T> : JsonConverter where 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\"}");

下面是输出屏幕截图

ki1q1bka

ki1q1bka2#

我把这个问题留着,希望有人能给出更好的答案,但我暂时使用了以下解决方案来解决我的问题。

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;
    }
}

相关问题