2014-09-10 2 views
2

У меня есть «база данных» Json, и я пытаюсь извлечь из него содержимое с помощью Newtonsoft Json.Net LINQ.Правильный синтаксис для запроса LINQ to JSON с вложенными массивами

Целью является извлечение свойства из элементов в дочернем массиве, содержащемся в элементе в родительском массиве. Элемент в родительском массиве будет выбран с помощью свойства ключа. «Внешний» элемент представляет собой массив с одной записью, «внутренний» элемент представляет собой массив из двух родительских записей, каждый из которых имеет «ключ» и массив дочерних элементов ». Глядя на соответствие внутреннему родительскому элементу по его ключу, а затем извлечь дочерние «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

Я думаю, что это то, что вы ищете для:

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

Ключом здесь является использование .SelectMany для сглаживания проецируемого itemid s в новый список.

+0

Отлично, спасибо! Я бы проигнорировал Select ** Many ** в каждой попытке –

+0

@BrianKretzler: Нет проблем. Я все еще работаю над тем, почему вызов 'Select' вызывал прямую ошибку (это для меня в любом случае). –

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; 
    } 
+0

Большое вам спасибо за это предложение. Хотя это может быть хорошим выбором для реализации, то, с чем я борюсь, это синтаксис запроса LINQ. Мне бы очень хотелось узнать, что не так с моими попытками сначала использовать запрос LINQ. –

+0

json linq выглядит уродливым. Я думаю, что его легче работать с linq для объектов. Вот хорошее место, где вы можете изучить linq http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b – Valentin

Смежные вопросы