本文介绍了反序列化不一致的JSON属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

希望有人可以帮助我解决使用Newtonsoft.Json反序列化的大型JSON文件中出现的以下不一致问题。

Hopefully someone can help me with the following inconsistency occurring in a large JSON file that I am attempting to deserialize using Newtonsoft.Json.

该对象的属性之一偶尔会显示为:

One of the properties of the object occasionally appears as:

"roles": [
  {
    "field1" : "value",
    "field2" : "value"
  }
]

其他情况下,同一属性显示为:

While other times that same property appears as:

"roles": {
  "roles": [
    {
      "field1" : "value",
      "field2" : "value"
    }
  ]
}

供参考,此属性在其类中实现as:

For reference, this property is implemented in its class as:

[JsonProperty("roles")]
public List<Role> Roles { get; set; }

我需要发生的是,无论何时出现上述第二种情况,对象内容都将像第一种情况。即外部对象被丢弃/忽略

当一个单独的属性有时作为对象出现并且有时作为数组使用以下方法时,我设法处理了该文件中的另一个不一致问题类定义:

I have managed to handle another inconsistency in this file when a separate property sometimes occurs as an object and sometimes as an array using the following approach in its class definition:

[JsonConverter(typeof(SingleValueArrayConverter<Address>))]
public List<Address> Location { get; set; }

并实现为:

public class SingleValueArrayConverter<T> : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        object retVal = new Object();
        if (reader.TokenType == JsonToken.StartObject)
        {
            T instance = (T)serializer.Deserialize(reader, typeof(T));
            retVal = new List<T>() { instance };
        }
        else if (reader.TokenType == JsonToken.StartArray)
        {
            retVal = serializer.Deserialize(reader, objectType);
        }
        return retVal;
    }

    public override bool CanConvert(Type objectType)
    {
        return true;
    }
}

但是,我无法解决此问题。
有人可以帮忙吗?

However, I am unable to work out this issue.Can anyone help?

推荐答案

您可以使用 JsonConverter 也。它将与您所拥有的稍有不同,但是想法非常相似:

You can handle this inconsistency with a JsonConverter also. It will be a little different than the one you have, but the idea is very similar:

public class ArrayOrWrappedArrayConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(List<T>).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        if (token.Type == JTokenType.Array)
        {
            return CreateListFromJArray((JArray)token, serializer);
        }
        if (token.Type == JTokenType.Object)
        {
            JObject wrapper = (JObject)token;
            JProperty prop = wrapper.Properties().FirstOrDefault();
            if (prop.Value.Type == JTokenType.Array)
            {
                return CreateListFromJArray((JArray)prop.Value, serializer);
            }
        }
        // If the JSON is not what we expect, just return an empty list.
        // (Could return null or throw an exception here instead if desired.)
        return new List<T>();
    }

    private List<T> CreateListFromJArray(JArray array, JsonSerializer serializer)
    {
        List<T> list = new List<T>();
        serializer.Populate(array.CreateReader(), list);
        return list;
    }

    public override bool CanWrite => false;

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

然后只需将转换器添加到您的 Roles 属性,那么您应该可以使用:

Then just add the converter to your Roles property and you should be good to go:

[JsonProperty("roles")]
[JsonConverter(typeof(ArrayOrWrappedArrayConverter<Role>))]
public List<Role> Roles { get; set; }

工作演示:

这篇关于反序列化不一致的JSON属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-27 14:04
查看更多