反序列化呈现为不同类型的节点

时间:2018-10-10 10:51:47

标签: c# json json.net

我正在遍历JSON文件的文件夹,并且试图从中提取一些信息;但是,我发现这样做非常困难。

我已经开始构建要反序列化的对象。我有一个通常会反序列化为对象的特定节点,但是当它为空时,它将显示为一个空数组。请在下面的示例JSON中查看definition字段:

{
  "name": "Example",
  "description": "Example JSON",
  "properties": {
    "foo": "bar",
    "foo1": "bar2",
    "foo3": "bar4"
  },
  "stages": {
    "This is a stage": {
      "stageInfo1": "blah",
      "stageInfo2": "blah",
      "integration": {
        "x": "x",
        "y": "y",
        "z": "z",
        "definition": []
      }
    },
    "Another Stage": {
      "stageInfo1": "blah",
      "stageInfo2": "blah",
      "integration": {
        "x": "x",
        "y": "y",
        "z": "z",
        "definition": {
          "5a4d7de4c6518": {
            "Editable": true,
            "ID": "5a4d7de4c6518",
            "Name": "My example"
          }
        }
      }
    }
  }
}

由于定义名称可以更改(在本例中为5a4d7de4c6518),我认为最好使用字典,但是在显示空数组时会引发错误。

 [JsonProperty("definition")]
 public Dictionary<string, Definition> definition;

错误:

  

Newtonsoft.Json.dll中发生了类型为'Newtonsoft.Json.JsonSerializationException'的未处理异常

     

其他信息:无法将当前JSON数组(例如[1,2,3])反序列化为类型'System.Collections.Generic.Dictionary`2 [System.String,JsonProcessReader.Models.Stages + IntegrationDefinition]',因为类型需要JSON对象(例如{“ name”:“ value”})才能正确反序列化。

     

要解决此错误,可以将JSON更改为JSON对象(例如{“ name”:“ value”}),也可以将反序列化类型更改为数组或实现集合接口的类型(例如ICollection,IList),例如可以从JSON数组反序列化的列表。还可以将JsonArrayAttribute添加到类型中,以强制其从JSON数组反序列化。

1 个答案:

答案 0 :(得分:3)

一个空数组与字典结构不兼容,这会引起您所看到的错误。由于似乎无法轻松更改JSON,因此需要使用JsonConverter来处理这种情况。这是一种通用的软件,适合您:

class TolerantObjectConverter<T> : JsonConverter where T: new()
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(T);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        object result = new T();
        if (token.Type == JTokenType.Object)
        {
            serializer.Populate(token.CreateReader(), result);
        }
        return result;
    }

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

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

此转换器的工作方式是将相关的JSON临时加载到JToken中,然后在尝试转换之前先检查它是否实际上是对象。因此,如果它是无法正确转换的数组或其他某种令牌类型,它将返回一个空的T实例。

要使用转换器,只需将[JsonConverter]属性添加到字典属性中,如下所示:

public class Integration
{
    ...
    [JsonConverter(typeof(TolerantObjectConverter<Dictionary<string, Definition>>))]
    public Dictionary<string, Definition> definition { get; set; }
}

这是一个有效的演示:https://dotnetfiddle.net/83dQoC