2016-03-31 12 views
0

Ich muss Benutzer auswählen, die eine "3" in ihrem JSON-Array haben.LINQ to JSON - Abfragen eines Arrays

{ 
    "People":[ 
    { 
     "id" : "123", 
     "firstName" : "Bill", 
     "lastName" : "Gates", 
     "roleIds" : { 
       "int" : ["3", "9", "1"] 
      } 
    }, 
    { 
     "id" : "456", 
     "firstName" : "Steve", 
     "lastName" : "Jobs", 
     "roleIds" : { 
      "int" : ["3", "1"] 
     } 
    }, 
    { 
     "id" : "789", 
     "firstName" : "Elon", 
     "lastName" : "Musk", 
     "roleIds" : { 
      "int" : ["3", "7"] 
     } 
    }, 
    { 
     "id" : "012", 
     "firstName" : "Agatha", 
     "lastName" : "Christie", 
     "roleIds" : { 
      "int" : "2" 
     } 
    } 
]} 

Am Ende sollte meine Ergebnisse Elon Musk & Steve Jobs sein. Dies ist der Code, den ich verwenden (& andere Variationen):

var roleIds = pplFeed["People"]["roleIds"].Children()["int"].Values<string>(); 


var resAnAssocInfo = pplFeed["People"] 
.Where(p => p["roleIds"].Children()["int"].Values<string>().Contains("3")) 
.Select(p => new 
{ 
    id = p["id"], 
    FName = p["firstName"], 
    LName = p["lastName"] 
}).ToList(); 

ich die folgende Fehlermeldung erhalten:

"Accessed JArray values with invalid key value: "roleIds". Int32 array index expected" 

I .Values<string>() zu .Values<int>() geändert und noch kein Glück.

Was mache ich falsch?

+0

Ihre JSON ungültig ist. Laden Sie es auf https://jsonformatter.curiousconcept.com/ hoch, um das Problem zu sehen. Möglicherweise '{" People ": [{{id": "123" ... 'sollte' {"People" sein: [{"id": "123" ... ', mit dem passenden'} 'auch vom Ende entfernt? – dbc

+0

Gutes Auge. Ich habe den JSON aktualisiert, um dem korrekten Format zu folgen. Es funktioniert jedoch immer noch nicht. Irgendeine Idee, was ich falsch mache? –

Antwort

2

Sie sind ziemlich nah. Ändern Sie Ihre Where Klausel aus dieser:

.Where(p => p["roleIds"].Children()["int"].Values<string>().Contains("3")) 

dazu:

.Where(p => p["roleIds"]["int"].Children().Contains("3")) 

und Sie erhalten Sie das gewünschte Ergebnis (obwohl es tatsächlich drei Benutzer in Ihrer Beispieldaten mit einer Rolle-ID von "3" sind , nicht zwei).

Es gibt jedoch ein anderes Problem, das Sie möglicherweise treffen, für die dieser Code immer noch nicht funktioniert. Sie werden bemerken, dass für Agatha Christie der Wert int kein Array wie die anderen ist, sondern eine einfache Zeichenfolge. Wenn der Wert manchmal ein Array ist und manchmal nicht, dann brauchen Sie eine WHERE-Klausel, die beide verarbeiten kann. So etwas sollte funktionieren:

.Where(p => p["roleIds"]["int"].Children().Contains(roleId) || 
      p["roleIds"]["int"].ToString() == roleId) 

... wo roleId ist eine Zeichenfolge, die die ID Sie suchen.

Fiddle: https://dotnetfiddle.net/Zr1b6R

1

Das Problem ist, dass nicht alle Objekte die gleiche Schnittstelle folgen. Das letzte Element in dieser Liste hat einen einzelnen Zeichenfolgenwert in der Eigenschaft roleIds.int, während alle anderen ein Array haben. Sie müssen diese Eigenschaft normalisieren und dann die Überprüfung durchführen. Es wäre am einfachsten, wenn sie alle Arrays wären.

sollten Sie in der Lage sein, dies zu tun:

var roleId = "3"; 
var query = 
    from p in pplFeed["People"] 
    let roleIds = p.SelectToken("roleIds.int") 
    let normalized = roleIds.Type == JTokenType.Array ? roleIds : new JArray(roleIds) 
    where normalized.Values().Contains(roleId) 
    select new 
    { 
     id = p["id"], 
     FName = p["firstName"], 
     LName = p["lastName"], 
    };