使用嵌套数组进行LINQ to JSON查询的正确语法

时间:2014-09-10 18:43:47

标签: c# json linq json.net

我有一个Json“数据库”,并尝试使用Newtonsoft Json.Net LINQ从中提取内容。

目标是从父数组中的项目中包含的子数组中的项目中提取属性。父数组中的项目将由键属性选择。 “outer”元素是一个带有一个条目的数组,“inner”元素是两个父条目的数组,每个条目都有一个“key”和一个子“item”数组。想要匹配内部父项它的键,然后将子数组中所有项的子“itemid”属性提取到IList中。

file at filePath contains:
{
   "outer":
   [
      {
         "inner":
         [
            {
               "key": "AAA",
               "items":
               [
                  { "itemid": "a1" }
               ]
            },
            {
               "key": "BBB",
               "items":
               [
                  { "itemid": "b1" },
                  { "itemid": "b2" }
               ]
            }
         ]
      }
   ]
}

我认为提取查询看起来像下面显示的那样,但是我尝试过的这几个或任何一个变种都没有成功。在某些变体中,它似乎一直工作到正确的内部“项目”的最终选择,但在尝试挖掘“itemid”数组时,我就崩溃了。 有什么线索在这里错了吗?如果需要,我愿意将其分成两个单独的查询。

public IList<string> FindMatchingItems(string filePath, string id)
{
    JObject JsonLinq = JObject.Parse(File.ReadAllText(filePath));
    return JsonLinq["outer"].First()["inner"].Children()
        .First(inner => inner["key"].ToString() == id)
        .Select(selected => selected["items"].Children()["itemid"].ToString())
        .ToList();
}

void Query(string filePath)
{
    var ayes = FindMatchingItems(filePath, "AAA");
    // ayes contains [] { "a1" }

    var bees = FindMatchingItems(filePath, "BBB");
    // bees contains [] { "b1", "b2" }
}

2 个答案:

答案 0 :(得分:2)

我认为这就是你要找的东西:

JsonLinq["outer"].First()["inner"]
    .Where(innerItem => innerItem["key"].Value<string>() == id)
    .SelectMany(innerItem => innerItem["items"]
        .Select(itm => itm["itemid"].Value<string>()))
    .ToList();

此处的关键是使用.SelectMany将预计的itemid展平为新列表。

答案 1 :(得分:1)

您可以在C#中创建一个类,然后使用JsonConvert.DeserializeObject()

C# class
public class Item
{
    public string itemid { get; set; }
}

public class Inner
{
    public string key { get; set; }
    public List<Item> items { get; set; }
}

public class Outer
{
public List<Inner> inner { get; set; }
}

public class RootObject
{
    public List<Outer> outer { get; set; }
 }

然后你可以使用

    public List<string> FindMatchingItems(string filePath, string id)
    {
        var json = File.ReadAllText(filePath);
        var rootObject = JsonConvert.DeserializeObject<RootObject>(json);
        var result = rootObject.outer.First().inner.First(i => i.key == id).items.Select(item => item.itemid).ToList();

        return result;
    }