反序列化不一致 JSON 属性

Deserialize inconsistent JSON property

希望有人可以帮助我解决我试图使用 Newtonsoft.Json.

反序列化的大型 JSON 文件中发生的以下不一致问题

对象的其中一个属性偶尔会显示为:

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

而其他时候 属性 显示为:

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

供参考,此属性在其class中实现为:

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

我需要发生的是,每当上述第二种情况发生时,对象内容像第一种情况一样被反序列化。即“外部”对象是 discarded/ignored

当单独的 属性 有时作为对象出现,有时作为数组出现时,我设法处理了此文件中的另一个不一致,在其 class 定义中使用以下方法:

[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;
    }
}

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

最简单的方法(不一定是最干净的)是在反序列化之前手动更改字符串 -

jsonString = jsonString.replace("\"roles\": {", "\"rolesContainer\": {");
jsonString = jsonString.replace("\"roles\":{", "\"rolesContainer\": {");

然后在您的主代码中,您会将 rolesContainer 和 roles 作为字段 - 然后在

之后合并它们
public List<Role> roles { get; set; }
public RoleContainer rolesContainer { get; set; }
public class RoleContainer {
    Public List<Role> roles;
}

有点脏,但应该可以用

您也可以使用 JsonConverter 处理这种不一致。它会与您拥有的略有不同,但想法非常相似:

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 属性 就可以了:

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

工作演示:https://dotnetfiddle.net/F6qgQB