有没有办法在数组中填充JSON对象中缺少的属性?

时间:2014-10-23 03:00:36

标签: c# json csv json.net

我在c#中使用JSON.NET来接触提供JSON作为输出的API。

我将该输出作为CSV打印到控制台,以便powershell convertfrom-csvformat-tableselect-object等可以使用它。

我有一个很好的通用方法可以将各种JSON打印为CSV,它几乎一直都在工作。

但是,在某些情况下,我会像这样获得JSON

{ 
    "result": 
    [ 
        { "product": "SP1", "version": "6.0" }, 
        { "product": "SP1 hf 40", "version": "6.0.40" }, 
        { "product": "SP1 hf 50", "version": "6.0.50" }, 
        { "version": "6.0.100" } 
    ] 
}

result中的最后一项完全缺少product属性。

有没有办法迭代result中的项目并输入缺少的属性,以便输出为:

{ 
    "result": 
    [ 
        { "product": "SP1", "version": "6.0" }, 
        { "product": "SP1 hf 40", "version": "6.0.40" }, 
        { "product": "SP1 hf 50", "version": "6.0.50" }, 
        { "product": "", "version": "6.0.100" } 
    ] 
}

这将允许我继续使用通用方法将JSON输出打印为CSV。

我的一个想法是迭代结果数组并找到具有最多属性的元素,并将其用作打印CSV的基础。

但是这个想法在它的表面上是相当平淡的,因为属性的数量并不一定能保证整个集合中的所有属性。

我想我几乎需要一个UNION类型的操作来查找数组所有元素中的所有属性。

很抱歉,如果这是一个非常愚蠢的问题,但我只是想知道是否可能。

2 个答案:

答案 0 :(得分:2)

当然,你可以做到。有许多方法可行。例如,你可以简单地做2次传球。在第一遍中,您构建了一个完整的属性列表,并在第二个传递输出到具有完整头的csv。

无论你如何攻击它,这种规范化在流式传输时都不会很好。

我还想指出Powershell 3.0及以上版本附带ConvertFrom-Json。 http://technet.microsoft.com/en-us/library/hh849898.aspx

答案 1 :(得分:0)

是的,可以在JSON中填写缺少的属性。以下是使用@BnWasteland建议的2遍方法的示例:

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        {
            ""result"" : 
            [
                { ""a"" : ""a1"" },
                { ""b"" : ""b1"" },
                { ""c"" : ""c1"", ""d"" : ""d1"", ""a"" : ""a2"" },
                { ""a"" : ""a3"", ""d"" : ""d2"" },
                { ""b"" : ""b2"", ""c"" : ""c2"" },
            ]
        }";

        JObject jo = JObject.Parse(json);
        JArray ja = FillMissingProperties((JArray)jo["result"]);
        jo["result"] = ja;
        Console.WriteLine(jo.ToString());
    }

    public static JArray FillMissingProperties(JArray array)
    {
        // find all distinct property names across all objects in the array
        ISet<string> names = new SortedSet<string>();
        foreach (JObject obj in array.Children<JObject>())
        {
            foreach (JProperty prop in obj.Properties())
            {
                names.Add(prop.Name);
            }
        }

        // copy objects to a new array, adding missing properties along the way
        JArray arrayOut = new JArray();
        foreach (JObject obj in array.Children<JObject>())
        {
            JObject objOut = new JObject();
            foreach (string name in names)
            {
                JToken val = obj[name];
                if (val == null)
                {
                    val = new JValue("");
                }
                objOut.Add(name, val);
            }
            arrayOut.Add(objOut);
        }

        return arrayOut;
    }
}

输出:

{
  "result": [
    {
      "a": "a1",
      "b": "",
      "c": "",
      "d": ""
    },
    {
      "a": "",
      "b": "b1",
      "c": "",
      "d": ""
    },
    {
      "a": "a2",
      "b": "",
      "c": "c1",
      "d": "d1"
    },
    {
      "a": "a3",
      "b": "",
      "c": "",
      "d": "d2"
    },
    {
      "a": "",
      "b": "b2",
      "c": "c2",
      "d": ""
    }
  ]
}