【问题标题】:JSON.NET deserialize JSON object stored as propertyJSON.NET 反序列化存储为属性的 JSON 对象
【发布时间】:2017-08-11 15:51:00
【问题描述】:

我有一条 JSON 消息要反序列化,其中包含另一个对象的 JSON 的字符串属性。我有以下课程

public class Envelope
{
    public string Type { get; set; }
    public Message InnerMessage { get; set; }
}

public class Message
{
    public string From { get; set; }
    public string To { get; set; }
    public string Body { get; set; }
}

我收到的 JSON 消息是这种格式:

{
    Type : "send",
    InnerMessage : "{ From: \"sender\", To: \"receiver\", Body: \"test\" }"
}

注意InnerMessage 包含Message 类的序列化,而不是类的JSON。

如果我将 InnerMessage 属性的类型保持为 Message,标准 JSON.NET 反序列化将失败。

如果我将InnerMessage 更改为string,序列化工作但在我需要再次将InnerMessage 的内容反序列化为Message 类之后:

Envelope envelope = JsonConvert.DeserializeObject<Envelope>(jsonMessage);
Message innerMessage = JsonConvert.DeserializeObject<Envelope>(envelope.InnerMessage);

有什么方法可以将EnvelopeInnerMessage 属性保留为Message,并告诉JSON.NET 将字符串值自动反序列化?

【问题讨论】:

  • 你是如何序列化你的对象的?当我使用 JsonConvert.SerializeObject(envelope) 时,我得到的 Json 输出与你不同。
  • 我从 web 服务获取 JSON,我只需要将其反序列化为我创建的类
  • 知道了,看起来@SirRufo 有你想要的答案

标签: c# json json.net deserialization


【解决方案1】:

你需要一个自定义的JsonConverter

class StringTypeConverter : Newtonsoft.Json.JsonConverter
{
    public override bool CanRead => true;
    public override bool CanWrite => true;

    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        string json = (string)reader.Value;
        var result = JsonConvert.DeserializeObject(json, objectType);
        return result;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var json = JsonConvert.SerializeObject(value);
        serializer.Serialize(writer, json);
    }
}

并将JsonConverterAttribute 添加到InnerMessage 属性

public class Envelope
{
    public string Type { get; set; }
    [Newtonsoft.Json.JsonConverter(typeof(StringTypeConverter))]
    public Message InnerMessage { get; set; }
}

public class Message
{
    public string From { get; set; }
    public string To { get; set; }
    public string Body { get; set; }
}

现在您可以序列化/反序列化 Envelope

var envelope = JsonConvert.DeserializeObject<Envelope>( jsonMessage );

【讨论】:

  • 谢谢,你的解决方案看起来比另一个更干净,明天我会测试它
【解决方案2】:

您可以使用自定义转换器来做到这一点。例如:

public class EnvelopeConverter : JsonConverter
{
    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)
    {
        var envelope = JObject.Load(reader);

        var type = envelope["Type"].ToString();
        var message = JsonConvert.DeserializeObject<Message>(
            envelope["InnerMessage"].ToString());

        return new Envelope
        {
            Type = type,
            InnerMessage = message
        };
    }

    public override bool CanRead
    {
        get { return true; }
    }

    public override bool CanConvert(Type objectType)
    {
        return true;
    }
}

并像这样使用它:

Envelope envelope = JsonConvert.DeserializeObject<Envelope>(
    jsonMessage, new EnvelopeConverter());

【讨论】:

  • 感谢您的回答,但我个人更喜欢 Rufo 爵士,因为我可以申请特定的房产而不是班级
猜你喜欢
  • 2014-08-22
  • 1970-01-01
  • 2013-07-09
  • 1970-01-01
  • 2018-09-18
  • 1970-01-01
  • 2017-03-21
  • 1970-01-01
相关资源
最近更新 更多