【问题标题】:How to interpret and deserialize this JSON response如何解释和反序列化这个 JSON 响应
【发布时间】:2018-04-11 18:31:35
【问题描述】:

此问题源自另一个主题,可在以下位置找到: Extract objects from JSON array to list

问题是我收到了以下 JSON 响应,而我的 JSON.NET 反序列化器不理解它,但是像 https://jsonlint.com 这样的其他几个 JSON 验证器说它是有效的。

[
{"value":"{\"code\":\"MO\",\"description\":\"Monday\",\"isSet\":false}","nr":1}
,{"value":"{\"code\":\"TU\",\"description\":\"Tuesday\",\"isSet\":true}","nr":2}
]

在我看来,这里的问题是值对象看起来像一个 JSON 对象,但实际上是一个字符串。 JsonConvert.DeserializeObject 一直抛出错误,直到我删除额外的引号 (") 和转义字符。

所以问题是,为什么这个响应格式是这样的?以及如何告诉反序列化器如何使用它?我确信删除或替换字符不是要走的路。

这是我正在做的:

public class Value
{
    public string code { get; set; }
    public string description { get; set; }
    public bool isSet { get; set; }
}

public class RootObject
{
    public Value value { get; set; }
    public int nr { get; set; }
}

var json = JsonConvert.DeserializeObject<List<RootObject>>(serviceResult);

以上行不通。

目前我已经通过这种方式解决了这个问题。但我一直认为,上面的解串器更优雅。

JArray jArray = JArray.Parse(serviceResult);
List<Value> values = jArray.Select(x => JObject.Parse(x["value"].ToString()).ToObject<Value>()).ToList();

【问题讨论】:

  • 能贴出反序列化代码吗?
  • 喜欢它是嵌套的。这些值本身是 json 样式的属性,并且使用转义引号对其进行编码以符合字符串的要求。
  • 对我来说看起来像是有效的 JSON,你想将它反序列化成什么?您链接的问题不正确。
  • 我已经添加了我当前的代码。
  • @DavidG 为什么这个问题不正确?

标签: c# json json.net


【解决方案1】:

最简单的方法是使用自定义JsonConverter,例如:

public class StringToObjectConverter<T> : Newtonsoft.Json.JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, 
        JsonSerializer serializer)
    {
        //This will only be needed if you also need to serlialise
        writer.WriteRaw(JsonConvert.SerializeObject(value));
    }

    public override object ReadJson(JsonReader reader, Type objectType, 
        object existingValue, JsonSerializer serializer)
    {
        return JsonConvert.DeserializeObject<T>(reader.Value.ToString());
    }

    public override bool CanRead => true;
    //We can only work with the type T, you could expand this to cope with derived types
    public override bool CanConvert(Type objectType) => typeof(T) == objectType;
}

现在使用这些模型,特别注意 Value 属性上的属性:

public class RootObject
{
    [JsonConverter(typeof(StringToObjectConverter<Value>))]
    public Value value { get; set; }
    public int nr { get; set; }
}

public class Value
{
    public string code { get; set; }
    public string description { get; set; }
    public bool isSet { get; set; }
}

现在是一个简单的反序列化:

var json = "....";
var rootObjects = JsonConvert.DeserializeObject<List<RootObject>>(json);

【讨论】:

  • 对。这看起来完全可以理解。谢谢你。但是,我一直在想,如果根据各种工具它是有效的 JSON,为什么最常用的 JSON.NET 库不支持 OOTB?
  • 嗯,这只是额外的复杂性,坦率地说,是不需要的。每次 James Newton(编写 JSON.Net 的人)添加另一个检查时,都会减慢每个人的解析速度。
  • 是的。知道服务开发人员增加这种额外复杂性的原因是什么吗?
  • 呃,谁知道呢!最好问问他们。他们可能使用不同的库来做不同的事情。请注意,JSON 规范并没有说应该将字符串转换为对象。想象一下,你偶然有一个看起来像 JSON 的字符串,我不希望我的解析器对它做任何聪明的事情。
  • 而不是WriteRaw() 我认为你需要在WriteJson() 中调用WriteValue()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多