如何解释和反序列化此JSON响应

时间:2018-04-11 09:51:34

标签: c# json json.net

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

问题是我收到了以下JSON响应,而我的JSON.NET反序列化程序并不理解它,但其他几个JSON验证程序(如https://jsonlint.com)表示它是有效的。

[
{"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();

1 个答案:

答案 0 :(得分: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);