无法取消异构json数据

时间:2017-08-01 03:12:45

标签: c# json json.net json-deserialization

所以我使用Json.net将REST API返回的json数据反序列化到服务器,它返回的数据结构是:

{ "keyXXX" : [[1,2,3,...]...], "last": 12345 }

问题是&#34;键&#34;也是数据的一部分,它不是一个名为&#34; key&#34;的字段,所以我不能使用类/结构,我必须使用IDictionary<string, int[][]>作为第一部分,但随后是&# 34;最后&#34; part将抛出异常,因为它是一个整数而不是一个数组数组。 这就是我尝试过的:

var dec = JsonConvert.DeserializeObject<IDictionary<string, int[][]>>(data);

抛出json异常:

  

Newtonsoft.Json.JsonSerializationException:将值1501555920转换为&#39; System.Decimal [] []&#39;时出错。路径&#39;最后&#39;。

//define a class
public class DPInfo
{
    public decimal[][] points { get; set; }
    public long last { get; set; }
}
var dec = JsonConvert.DeserializeObject<DPInfo>(data);

这不起作用,因为数组的字段名称是动态的,因此points之后将不包含任何内容。

我能解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

您可以使用JObject.Parse将字符串解析为dynamic变量。它至少可以确保从字符串到JSON的转换成功,但是在您访问它之前,需要验证每个属性中是否有值。

在您的情况下,该陈述将如下所示:

dynamic data = JObject.Parse("{ 'keyXXX' : [[1,2,3,...]...], 'last': 12345 }");

答案 1 :(得分:1)

您需要自定义JsonConverter来解决此问题。这是一个应该工作的:

public class DPInfoConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DPInfo);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject obj = JObject.Load(reader);
        JProperty points = obj.Properties().FirstOrDefault(p => p.Name != "last");

        DPInfo info = new DPInfo
        {
            key = points.Name,   // remove this line if you don't need the key
            points = points.Value.ToObject<decimal[][]>(),
            last = (long)obj["last"]
        };

        return info;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

要使用它,只需在您的班级中添加[JsonConverter]属性:

[JsonConverter(typeof(DPInfoConverter))]
public class DPInfo
{
    public string key { get; set; }   // remove this line if you don't need the key
    public decimal[][] points { get; set; }
    public long last { get; set; }
}

然后,像往常一样反序列化,它应该工作:

string json = @"
{
  ""keyXXX"": [[1, 2, 3]],
  ""last"": 12345
}";

DPInfo info = JsonConvert.DeserializeObject<DPInfo>(json);

小提琴:https://dotnetfiddle.net/7S6STp