【问题标题】:How do I deserialize a property containing an escaped JSON string? [duplicate]如何反序列化包含转义 JSON 字符串的属性? [复制]
【发布时间】:2018-01-25 18:17:56
【问题描述】:

我有一个来自 API 的 application/json 响应,该 API 本身具有包含转义 JSON 字符串的属性。

{
    "id": 0,
    "aggregation_id": "533741f4-49da-4db9-9660-4ca7bafb30e1",
    "task_id": "217",
    "event_type": "discovery",
    "event_name": "device_discovery_complete",
    "method": "ssh",
    "message_details": "{\"aggregation_id\":\"533741f4-49da-4db9-9660-4ca7bafb30e1\",\"ou_id\":0,\"device_id\":13,\"node_id\":13,\"task_id\":217}",
    "time": "2018-01-25T17:59:25"
  }

我想将对象和内部对象反序列化为模型类型。

public class Response
{
    public DateTime time {get; set;}
    public string event_name {get; set;}
    public string event_type {get; set;}
    public string method {get; set;}
    public MessageDetails message_details {get; set;}
}

public class MessageDetails
{
    public int device_id {get; set;}
}

使用这样的调用

JsonConvert.DeserializeObject<Response>("... response string...");

但是,Netwonsoft.Json 可以很好地处理外部属性,但在匹配 message_details 时会引发异常。

Newtonsoft.Json.JsonSerializationException: Error converting value "... response string snipped ..." to type 'RpcApi.Entities.MessageDetails'. 
Path '[0].message_details', line 1, position 390. 
---> System.ArgumentException: Could not cast or convert from System.String to RpcApi.Entities.MessageDetails.

【问题讨论】:

  • 您是否尝试在转换之前从序列化的 json 中删除 \?
  • 我希望尽可能避免预处理响应字符串。如果有办法告诉 Newtonsoft.Json 如何处理嵌套的 JSON 字符串。
  • 您的问题是 "message_details" 实际上是序列化的 JSON 作为字符串嵌入。如果您无法修复传入的 JSON,您可以使用来自 C# - How can I convert escape string JSON values within a JSON object into literal JSON?EmbeddedLiteralConverter&lt;MessageDetails&gt;
  • 我希望避免预处理,好吧,你要么做预处理,要么做后处理。没有其他办法。对于后处理,将MessageDetails 设为字符串,添加另一个属性,如MessageDetailsDeserialized,反序列化对象,然后将MessageDetails 反序列化为MessageDetailsDeserialized
  • 啊,我的问题怎么被标记为与负分问题的重复?!我是从端到端类型序列化的角度来问的,另一个问题是关于清理输入字符串 first 的问题。观点很重要!

标签: c# json.net


【解决方案1】:

您可以为此使用自定义的 JsonConverter,类似于:

public class EmbeddedJsonConverter : 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)
    {
        return serializer.Deserialize(new StringReader((string)reader.Value), objectType);
    }

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

[JsonConverter(typeof(EmbeddedJsonConverter))] 标记属性,例如:

public class Response
{
    public DateTime time { get; set; }
    public string event_name { get; set; }
    public string event_type { get; set; }
    public string method { get; set; }

    [JsonConverter(typeof(EmbeddedJsonConverter))]
    public MessageDetails message_details { get; set; }
}

然后你就可以用JsonConvert.DeserializeObject&lt;Response&gt;()反序列化了。

EmbeddedJsonConverter 类从对象中提取 json 字符串,然后对其进行反序列化。 CanConvert 可能应该变得更智能,以实现真正的通用用途。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-27
    • 2016-01-28
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多