【问题标题】:Failed to desirialize heterogeneous json data反序列化异构json数据失败
【发布时间】:2018-01-07 18:16:48
【问题描述】:

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

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

问题是“key”也是数据的一部分,它不是一个名为“key”的字段,所以我不能使用类/结构,我必须在第一部分使用IDictionary<string, int[][]>,但随后“最后”部分将引发异常,因为它是单个整数而不是数组数组。 这是我尝试过的:

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

这会引发 json 异常:

Newtonsoft.Json.JsonSerializationException:将值 1501555920 转换为类型“System.Decimal[][]”时出错。路径“最后一个”。

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

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

有什么办法可以解决这个问题?

【问题讨论】:

  • JSON 中是否只有一个keyXXX 或多个具有不同XXX 值的XXX
  • 只有一个,但名称不同

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


【解决方案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

【讨论】:

    【解决方案2】:

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

    在您的情况下,语句如下所示:

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

    【讨论】:

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