2016-07-25 13 views
0

Kann jemand einen Rat geben, vielleicht mit einem Code-Snippet, mit C# und json.net, um einige verschachtelte JSON zu lesen? Mein JSON unten validiert mit JSONLint zu einem guten JSON. Ich habe eine Hürde, dass ich beim Parsen der JSON nicht in die 3., 4., 6. und 8. Werte in der Wurzel verschachtelt bekommen kann.Geschachtelte JSON mit C# NewtonSoft

[{ 
"interactionType": "MathEditorInteraction", 
"interactionId": "08506178-22ba-4fa7-a490-c785716f10dc", 
"value": "blah blah blah" 
}, 
{ 
"interactionType": "MathEditorInteraction", 
"interactionId": "1134871f-980e-4138-9598-0d4bf480aa97", 
"value": "my first value" 
}, 
{ 
"interactionType": "CanvasInteraction", 
"interactionId": "89cd7bec-d0e8-4111-8442-f2ab95a1410b", 
"value": "my second value" 
}, 
{ 
"interactionType": "FillInBlankInteraction", 
"interactionId": "7e9350b4-fb85-4f12-869e-227f99f77a73", 
"value": "{\"results\":[{\"id\":\"1ac6770e-2093-4b7c-b595-789be8ee6efb\",\"value\":\"my third value\"}]}" 
}, 
{ 
"interactionType": "FillInBlankInteraction", 
"interactionId": "6f1ca6b7-3178-44a7-b8e9-e82d8c51d1fd", 
"value": "{\"results\":[{\"id\":\"b7e92fd2-9c7a-4f71-88f9-e7d43e3179b7\",\"value\":\"my fourth value\"}]}" 
}, 
{ 
"interactionType": "TextBoxInteraction", 
"interactionId": "284c43f9-a268-4295-b96d-bc2f6dc30f0e", 
"value": "my fifth value" 
}, 
{ 
"interactionType": "FillInBlankInteraction", 
"interactionId": "544b9907-139a-4c78-9671-502153be2697", 
"value": "{\"results\":[{\"id\":\"f4e1ba6d-61dd-4eed-9c6f-dafc2701c161\",\"value\":\"my sixth value\"}]}" 
}, 
{ 
"interactionType": "TextBoxInteraction", 
"interactionId": "c0a5a1f0-2cae-42fd-8726-0ad36c11f413", 
"value": "my seventh value" 
}, 
{ 
"interactionType": "FillInBlankInteraction", 
"interactionId": "ef6a7b62-8a7b-4b7f-b876-0d78ee6c4c87", 
"value": "{\"results\":[{\"id\":\"af39469e-c041-4889-9e28-61a438cf56a3\",\"value\":\"my eight value\"}]}" 
}, 
{ 
"interactionType": "TextBoxInteraction", 
"interactionId": "f04de5b5-8a29-4200-a886-15f7dbd575b6", 
"value": "my nineth value" 
}] 

dann einige C#, die ich verwendet haben:

JArray token = JArray.Parse(response); // response = json string above 
for (int i = 0; i < token.Count; i++) 
{ 
    String value = token[i]["value"].ToString(); 
} 

ich mit dem JSON i verbrauchen überrascht sein könnte ... es könnte n-count verschachtelt Werte ... der Zweck Mein Code ist es, zum untersten Kind mit der Zeichenfolge "value" zu gelangen. Gibt es eine Möglichkeit, ein Token [i] ["einige Zeichenfolge"] zu sehen und zu sehen, ob es ein JArray oder JObject enthält, um mit der Analyse fortzufahren?

EDIT von Timothy's Vorschlag, konnte ich die Werte ausgeben. Fast dort.

static string json2 = @"[{""interactionType"": ""MathEditorInteraction"",""interactionId"": ""08506178-22ba-4fa7-a490-c785716f10dc"",""value"": ""blah blah blah""},{""interactionType"": ""MathEditorInteraction"",""interactionId"": ""1134871f-980e-4138-9598-0d4bf480aa97"",""value"": ""my first value""},{""interactionType"": ""CanvasInteraction"",""interactionId"": ""89cd7bec-d0e8-4111-8442-f2ab95a1410b"",""value"": ""my second value""},{""interactionType"": ""FillInBlankInteraction"",""interactionId"": ""7e9350b4-fb85-4f12-869e-227f99f77a73"",""value"": ""{\""results\"":[{\""id\"":\""1ac6770e-2093-4b7c-b595-789be8ee6efb\"",\""value\"":\""my third value\""}]}""},{""interactionType"": ""FillInBlankInteraction"",""interactionId"": ""6f1ca6b7-3178-44a7-b8e9-e82d8c51d1fd"",""value"": ""{\""results\"":[{\""id\"":\""b7e92fd2-9c7a-4f71-88f9-e7d43e3179b7\"",\""value\"":\""my fourth value\""}]}""},{""interactionType"": ""TextBoxInteraction"",""interactionId"": ""284c43f9-a268-4295-b96d-bc2f6dc30f0e"",""value"": ""my fifth value""},{""interactionType"": ""FillInBlankInteraction"",""interactionId"": ""544b9907-139a-4c78-9671-502153be2697"",""value"": ""{\""results\"":[{\""id\"":\""f4e1ba6d-61dd-4eed-9c6f-dafc2701c161\"",\""value\"":\""my sixth value\""}]}""},{""interactionType"": ""TextBoxInteraction"",""interactionId"": ""c0a5a1f0-2cae-42fd-8726-0ad36c11f413"",""value"": ""my seventh value""},{""interactionType"": ""FillInBlankInteraction"",""interactionId"": ""ef6a7b62-8a7b-4b7f-b876-0d78ee6c4c87"",""value"": ""{\""results\"":[{\""id\"":\""af39469e-c041-4889-9e28-61a438cf56a3\"",\""value\"":\""my eight value\""}]}""},{""interactionType"": ""TextBoxInteraction"",""interactionId"": ""f04de5b5-8a29-4200-a886-15f7dbd575b6"",""value"": ""my ninth value""}]"; 

var x = JsonConvert.DeserializeObject<Interaction[]>(json2); 
for (int i = 0; i < x.Length; i++) 
{ 
if (x[i].value.Contains("[{")) 
    { 
     var v = JsonConvert.DeserializeObject<Nested>(x[i].value); 
     Console.WriteLine(v.results[0].value); 
    } 
else 
    { 
     Console.WriteLine(x[i].value); 
    }  
} 

Console Output:

blah blah blah 
my first value 
my second value 
my third value 
my fourth value 
my fifth value 
my sixth value 
my seventh value 
my eight value 
my ninth value 

Noch klebt tatsächlich eine Reihe tiefer als die erste Ebene zu erfassen. Sie können meinen Hack sehen, um nach "[{" zu suchen, was nicht bevorzugt wird.

EDIT: KUDOS an Jens für die Hilfe bei der Lösung, die ich heute brauchte. Sehen Sie die Kommentare unten für vollständige Erklärungen.

Antwort

2

Sie mit Deserialize können JToken.Type reagieren, wenn Sie möchten, um Objekte Deserialisieren nicht gehen. Ich arbeite meistens mit dem JSON in einer dynamischen Fasion in C#, ohne es in starke Typen zu deserialisieren. Das liegt hauptsächlich daran, dass wir mit Backends arbeiten, wo die Datenstrukturen von den Clients definiert werden und wir viel handhaben müssen mehr dynamische Daten.

https://dotnetfiddle.net/awUSGT

dynamic arr = JArray.Parse(JSON); // response = json string above 

    foreach (dynamic token in arr) 
    { 
     JTokenType type = ((JToken)token.value).Type; 

     switch (type) 
     { 
      case JTokenType.String: 
       Console.WriteLine(token.value); 
       break; 

      case JTokenType.Object: 
       Console.WriteLine(token.value.results.Last.value); 
       break; 
     } 
    } 

Beachten Sie, dass für vor 8.x oder 9.x (kann mich nicht erinnern, wenn ich diese fix gebucht) die oben etwas wird eine Ausnahme ausgelöst, wenn auf JToken Gießen.

kann also stattdessen tun:

dynamic arr = JArray.Parse(JSON); // response = json string above 

    foreach (JObject token in arr) 
    { 
     dynamic value = token["value"]; 
     switch (token["value"].Type) 
     { 
      case JTokenType.String: 
       Console.WriteLine(value); 
       break; 

      case JTokenType.Object: 
       Console.WriteLine(value.results.Last.value); 
       break; 
     } 
    } 

Jetzt als für eine abschließende Bemerkung, das Werkzeug i Ihre JSON prettify verwendet schien etwas zu entkommen für Ihre Werte abstreifen.

Ich weiß nicht, ob es absichtlich war, dass Sie Ihre eingebettete JSON als Zeichenfolgen (Serialized JSON) haben, wenn ja, müssen Sie eine Möglichkeit finden, das zu entdecken und dann auch zu analysieren.

könnte ein loser/entspannt Ansatz:

dynamic arr = JArray.Parse(JSON); // response = json string above 

    foreach (dynamic token in arr) 
    { 
     string tokenvalue = (string) token.value; 
     JToken value = Regex.IsMatch(tokenvalue, "^\\{.*\\}$") 
      ? JToken.Parse(tokenvalue) 
      : token.value; 
     switch (value.Type) 
     { 
      case JTokenType.String: 
       Console.WriteLine(value); 
       break; 

      case JTokenType.Object: 
       Console.WriteLine(((dynamic)value).results.Last.value); 
       break; 
     } 
    } 

Da ich nicht genau wissen, wie Sie Ihre „rekursive Verschachtelung“ aussieht, ist es schwer zu erraten, aber etwas entlang der Linien von:

public static void Main() 
{ 
    dynamic arr = JArray.Parse(JSON); // response = json string above 

    foreach (dynamic token in arr) 
    { 
     JToken value = ExtractValue(token); 
     Console.WriteLine(value); 
    } 
} 

private static JToken ExtractValue(dynamic token) 
{ 
    string tokenvalue = (string) token.value; 
    JToken value = Regex.IsMatch(tokenvalue, "^\\{.*\\}$") 
     ? JToken.Parse(tokenvalue) 
     : token.value; 

    switch (value.Type) 
    { 
     case JTokenType.String: 
      return value; 

     case JTokenType.Object: 
      return ExtractValue(((dynamic) value).results.Last); 

     default: 
      throw new InvalidOperationException("Could not extract data, unknown json construct."); 
    } 
} 

Vielleicht.

+0

Jens, Ihr Code wird das vollständige Sub-Array ausgeben, wenn ein JTokenType.Object statt des geschachtelten Werts angezeigt wird. Aber sehr nah an dem, was ich suche. –

+0

Der lockere/entspannte Ansatz funktioniert, aber nur eine Ebene tief in der Verschachtelung. Ich muss einen Weg finden, Verschachtelung dynamisch zu erkennen und Ihre Logik anzuwenden. Etwas Rekursives, über das ich noch nachdenke ... wenn du irgendwelche Vorschläge hast ?? mein Gehirn steuert auf eine Art von Versuch/Fang innerhalb einer Do/While-Schleife zu, die wahrscheinlich nicht die beste Wahl ist –

+0

Da Sie kein Beispiel dafür geben, wie diese tiefe Verschachtelung genau aussieht, ist es nicht einfach, den Nagel zu treffen richtig, aber ich habe ein Beispiel hinzugefügt, das zumindest inspirieren könnte. – Jens

0

Versuchen Sie es mit dieser: JsonConvert.DeserializeObject<Interaction[]>(yourJson);

wo Interaction ist:

public class Interaction 
{ 
    public string interactionType {get;set;} 
    public string interactionId {get;set;} 
    public string value {get;set;} 
} 

Dann wird für diejenigen, die eine verschachtelte JSON haben, können Sie dann einfach analysieren die value Eigenschaft von ihnen wie die folgenden:

public class Nested 
{ 
    public Result[] results {get;set;} 
} 

public class Result 
{ 
    public string id {get;set;} 
    public string value {get;set;} 
} 

Dann es wie folgt analysieren:

var v = JsonConvert.DeserializeObject<Nested>(x[8].value); 
+0

Sehr hilfreich Timothy. Ich konnte die Rohwerte aus Ihrem Beispiel mit ein paar kleinen Modifikationen nachvollziehen. –

0

können Sie leicht Modellklassen mit this service

Mit diesem Modell erzeugen können Sie leicht Newtonsoft Json

Verwandte Themen