Como faço para obter uma propriedade profundamente aninhada da string JSON?

Como posso obter o array “myThings” do JSON que se parece com o seguinte usando o JSON.NET?

Exemplo 1:

{ "z": { "a": 1, "b": 2 }, "something": { "y": [1, 2], "somethingElse": { "1234": { "foo": "bar", "myThings": [{ "name": "bob", "age": 3 }, { "name": "bob", "age": 3 }] } } } } 

Exemplo 2:

 { "z": { "a": 1, "b": 2 }, "something": { "y": [1, 2], "somethingElse": { "7890": { "foo": "bar" } } } } 

Algumas coisas com as quais estou tendo dificuldades:

  • Um dos nomes de propriedade é um número imprevisível (“1234” e “7890”)
  • Às vezes, a matriz “myThings” não existe – neste caso, null ou uma matriz / coleção vazia é o que eu quero ter

Outra consideração, caso isso ajude você: Eu tenho uma class estática que representa as coisas dentro da matriz myThings, então meu valor de retorno ideal seria IEnumerable

Minha primeira tentativa foi usar JsonConvert.DeserializeObject(json) mas não sei como lidar com os problemas que mencionei acima. No final, eu não preciso de todos os dados da string JSON, apenas aquele array interno chamado “myThings”.

Você pode usar o JToken.SelectTokens() para essa finalidade. Ele permite a consulta do JSON usando curingas e pesquisas recursivas usando a syntax JSONPath :

 var root = JToken.Parse(json); var myThings = root.SelectTokens("..myThings[*]").ToList(); 

Aqui ".." é o operador de descida recursiva e "myThings[*]" significa retornar todos os itens da matriz "myThings" .

Violino de protótipo.

Se as inputs da matriz de "myThings[*]" corresponderem a algum POCO MyThing , você poderá usar JToken.ToObject() para desserializá-las após consultar:

  var myThings = root.SelectTokens("..myThings[*]").Select(t => t.ToObject()).ToList();