简体   繁体   English

无法反序列化当前的JSON对象(空数组)

[英]Cannot Deserialize the Current JSON Object (Empty Array)

I am trying to make this program that formats all these objects into a treeview, to do this (I'm using JSON for ordering the objects), I needed to parse the JSON, so I chose JSON.NET. 我试图使这个程序将所有这些对象格式化为树视图,为此(我使用JSON来排序对象),我需要解析JSON,所以我选择了JSON.NET。

So here is an example of how the formatting is: 以下是格式化的示例:

{
    "Space": {
        "ClassName": "SpaceObject",
        "Name": "Space",
        "Children": {
            "Object1": {
                "ClassName": "Object",
                "Name": "Object1",
                "Children": []
            },
            "Object2": {
                "ClassName": "Object",
                "Name": "Object2",
                "Children": []
            }
        }
    }
}
public class CObject 
{
    [JsonProperty(PropertyName = "Name")]
    public string Name { get; set; }

    [JsonProperty(PropertyName = "ClassName")]
    public string ClassName { get; set; }

    [JsonProperty(PropertyName = "Children")]
    public IDictionary<string, CObject> Children { get; set; }
}
IDictionary<string, CObject> obj = JsonConvert.DeserializeObject<IDictionary<string, CObject>>(Json, new JsonSerializerSettings() {
    MissingMemberHandling = MissingMemberHandling.Ignore,
    NullValueHandling = NullValueHandling.Ignore,
});
foreach (var i in obj) {
    ExplorerView1.Nodes.Add(AddObject(i.Value));
}

I believe I found the error, it's due to a children array having no objects in it. 我相信我发现了错误,这是由于子数组中没有任何对象。 I don't know how to fix this though, can anyone help? 我不知道如何解决这个问题,任何人都可以帮忙吗?

JsonSingleOrEmptyArrayConverter<T> from this answer to Deserialize JSON when type can be different almost does what you need. JsonSingleOrEmptyArrayConverter<T>这个答案反序列化JSON,当类型可以不同时几乎JsonSingleOrEmptyArrayConverter<T>你的需要。 It simply needs to be enhanced to allow the current contract type to be a dictionary contract as well as an object contract. 只需要增强它以允许当前的合同类型是字典合同以及对象合同。

First, modify JsonSingleOrEmptyArrayConverter<T> as follows: 首先,修改JsonSingleOrEmptyArrayConverter<T> ,如下所示:

public class JsonSingleOrEmptyArrayConverter<T> : JsonConverter where T : class
{
    //https://stackoverflow.com/questions/29449641/deserialize-json-when-type-can-be-different?rq=1
    public override bool CanConvert(Type objectType)
    {
        return typeof(T).IsAssignableFrom(objectType);
    }

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var contract = serializer.ContractResolver.ResolveContract(objectType);
        // Allow for dictionary contracts as well as objects contracts, since both are represented by 
        // an unordered set of name/value pairs that begins with { (left brace) and ends with } (right brace).
        if (!(contract is Newtonsoft.Json.Serialization.JsonObjectContract 
              || contract is Newtonsoft.Json.Serialization.JsonDictionaryContract))
        {
            throw new JsonSerializationException(string.Format("Unsupported objectType {0} at {1}.", objectType, reader.Path));
        }

        switch (reader.SkipComments().TokenType)
        {
            case JsonToken.StartArray:
                {
                    int count = 0;
                    while (reader.Read())
                    {
                        switch (reader.TokenType)
                        {
                            case JsonToken.Comment:
                                break;
                            case JsonToken.EndArray:
                                // You might want to allocate an empty object here if existingValue is null
                                // If so, do
                                // return existingValue ?? contract.DefaultCreator();
                                return existingValue;
                            default:
                                {
                                    count++;
                                    if (count > 1)
                                        throw new JsonSerializationException(string.Format("Too many objects at path {0}.", reader.Path));
                                    existingValue = existingValue ?? contract.DefaultCreator();
                                    serializer.Populate(reader, existingValue);
                                }
                                break;
                        }
                    }
                    // Should not come here.
                    throw new JsonSerializationException(string.Format("Unclosed array at path {0}.", reader.Path));
                }

            case JsonToken.Null:
                return null;

            case JsonToken.StartObject:
                existingValue = existingValue ?? contract.DefaultCreator();
                serializer.Populate(reader, existingValue);
                return existingValue;

            default:
                throw new InvalidOperationException("Unexpected token type " + reader.TokenType.ToString());
        }
    }

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

public static partial class JsonExtensions
{
    public static JsonReader SkipComments(this JsonReader reader)
    {
        while (reader.TokenType == JsonToken.Comment && reader.Read())
            ;
        return reader;
    }
}

Then deserialize as follows: 然后反序列化如下:

var settings = new JsonSerializerSettings
{
    MissingMemberHandling = MissingMemberHandling.Ignore,
    NullValueHandling = NullValueHandling.Ignore,               
    Converters = { new JsonSingleOrEmptyArrayConverter<IDictionary<string, CObject>>() },
};

var obj = JsonConvert.DeserializeObject<IDictionary<string, CObject>>(Json, settings);

Notes: 笔记:

  • My assumption is that an empty array [] is only used when there are no children. 我的假设是只在没有子节点时才使用空数组[] If the array is ever nonempty, this assumption will be wrong and the converter will not work correctly. 如果数组是非空的,则此假设将是错误的并且转换器将无法正常工作。

  • The converter returns a null value for an empty array. 转换器为空数组返回null值。 If you would instead prefer an empty dictionary, uncomment the following lines: 如果您更喜欢空字典,请取消注释以下行:

     // You might want to allocate an empty object here if existingValue is null // If so, do // return existingValue ?? contract.DefaultCreator(); 

Working .Net fiddle here . 在这里工作.Net小提琴。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法反序列化当前的JSON对象 - Cannot deserialize the current JSON object 无法反序列化当前的 JSON 对象 - Cannot deserialize the current JSON object 无法反序列化当前JSON对象 - Cannot deserialize the current JSON object 无法反序列化当前JSON数组 - Cannot deserialize the current JSON array 无法反序列化当前JSON数组 - Cannot deserialize the current JSON array 无法反序列化当前 JSON object 因为该类型需要 JSON 数组(例如 [1,2,3])才能正确反序列化 - Cannot deserialize the current JSON object because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly 将复杂的JSON反序列化为对象-出现错误无法反序列化当前JSON数组(例如[1,2,3]) - Deserialize complex JSON into Object - getting error Cannot deserialize the current JSON array (e.g. [1,2,3]) 如何解决“无法将当前的 JSON 数组反序列化为类型,因为该类型需要 JSON object 才能正确反序列化。” - How to solve “Cannot deserialize the current JSON array into type because the type requires a JSON object to deserialize correctly.” 无法将 json object 反序列化为数组 - Cannot deserialize json object into array 无法将 JSON 数组反序列化为对象 - Cannot deserialize the JSON array to object
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM