使用空白数组反序列化 JSON 对象

Posted

技术标签:

【中文标题】使用空白数组反序列化 JSON 对象【英文标题】:Deserialize JSON object with blank array 【发布时间】:2016-05-23 07:25:11 【问题描述】:

当有一个空/空属性(使用 JSON.NET)时,我在反序列化 JSON 对象时遇到了一些麻烦,希望有人能指出我正确的方向。下面是我正在尝试的一段代码,并在dotnetfiddle进行测试

这是 JSON 的示例:


    "`LCA0009": [],
    "`LCA0001": 
        "23225007190002": "1",
        "23249206670003": "1",
        "01365100070018": "5"
    ,
    "`LCA0003": 
        "23331406670018": "1",
        "24942506670004": "1"
    ,
    "`LCA0005": 
        "01365100070018": "19"
    

我正在尝试使用此代码:

using System;
using System.Collections.Generic;
using Newtonsoft.Json;

public class Program

    public static void Main()
    

        string json = "\"`LCA0009\": [], \"`LCA0001\": \"23225007190002\": \"1\",\"23249206670003\": \"1\",\"01365100070018\": \"5\",\"`LCA0003\": \"23331406670018\": \"1\",\"24942506670004\": \"1\",\"`LCA0005\": \"01365100070018\": \"19\"";
        Console.WriteLine(json);
        Console.WriteLine();

        Console.WriteLine("This works");
        var root = JsonConvert.DeserializeObject(json);
        Console.WriteLine(root);

        Console.WriteLine("This doesn't work");
        var root2 = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, int>>>(json);
        Console.WriteLine(root2);

        foreach (var locationKvp in root2)
        
            foreach (var skuKvp in locationKvp.Value)
            
                Console.WriteLine("location: " + locationKvp.Key + ", sku: " +  skuKvp.Key + ", qty: " + skuKvp.Value);
            
        
    

上面的“不起作用”是我收到此错误:

运行时异常(第 19 行):无法将当前 JSON 数组(例如 [1,2,3])反序列化为类型“System.Collections.Generic.Dictionary`2[System.String,System.Int32]”因为该类型需要一个 JSON 对象(例如 "name":"value")才能正确反序列化。 要修复此错误,请将 JSON 更改为 JSON 对象(例如 "name":"value")或将反序列化类型更改为数组或实现集合接口的类型(例如 ICollection、IList),例如可以从 JSON 数组反序列化。 JsonArrayAttribute 也可以添加到类型中以强制它从 JSON 数组反序列化。 路径“LCA0009”,第 1 行,位置 14。

如何删除具有 null/空数组的属性?

【问题讨论】:

根本问题是 JSON 不一致,为某些条目提供了一个数组,而为其他条目提供了一个对象。解决此问题的最佳位置是生成 JSON 的位置:而不是 "`LCA0009": [],应该是 "`LCA0009": 修复 JSON fixes the problem. @T.J. Crowder - 不幸的是,我无法控制来源。我想我可以通过一些字符串替换函数将 [] 转换为 ,这将作为一种解决方法,直到我改变了源代码。 我会向控制源的人提供反馈,告诉他们他们做错了什么。不幸的是,字符串替换会有问题,因为 JSON 需要一个完整的解析器,简单的正则表达式不适合它。 【参考方案1】:

从根本上说,JSON 是不一致的,最好的答案是使其保持一致。谁给你 JSON 需要被告知修复它。

除非/除非你能这样做,否则你可以自己将“原始”版本转换为Dictionary&lt;string, Dictionary&lt;string, int&gt;&gt;,但这需要更多的工作:

https://dotnetfiddle.net/zdeOOX

string json = "\"`LCA0009\": [], \"`LCA0001\": \"23225007190002\": \"1\",\"23249206670003\": \"1\",\"01365100070018\": \"5\",\"`LCA0003\": \"23331406670018\": \"1\",\"24942506670004\": \"1\",\"`LCA0005\": \"01365100070018\": \"19\"";

// Convert it
var root = (JObject)JsonConvert.DeserializeObject(json);
var results = new Dictionary<string, Dictionary<string,int>>();
foreach (var entry in root)

    var dict = new Dictionary<string,int>();
    if (!(entry.Value is JArray))
    
        foreach (var subentry in (JObject)entry.Value)
        
            int v;
            if (int.TryParse(((JValue)subentry.Value).ToString(), out v))
            
                dict.Add(subentry.Key, v);
            
        
    
    results.Add(entry.Key, dict);


// Results:
foreach (var name in results.Keys)

    var entry = results[name];
    Console.WriteLine(name + ":");
    foreach (var entryKey in entry.Keys)
    
        Console.WriteLine("- " + entryKey + ": " + entry[entryKey]);
    

我希望使用 Linq 可以使其更加优雅。

【讨论】:

以上是关于使用空白数组反序列化 JSON 对象的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Jackson 反序列化来自 json 对象的对象数组

Json 使用动态属性名称反序列化对象数组

JSON PHP中,Json字符串反序列化成对象/数组的方法

使用 Json.net 反序列化 JSON 对象数组

有时是数组有时是对象时反序列化JSON

使用 Newtonsoft 反序列化未命名数组的 JSON 数组