2017-05-21 3 views
3

Ich verwende Newtonsoft.Json, um mit einigen JSON-Daten zu arbeiten, die mir zurückgegeben werden. Je nachdem, was ich verlangen kann ich entweder wieder etwas, das wie folgt aussieht:JSON-Einzelobjekt und Array behandeln

{ 
"TotalRecords":2, 
"Result": 
    [ 
     { 
     "Id":24379, 
     "AccountName":"foo" 
     }, 
     { 
     "Id":37209, 
     "AccountName":"bar" 
     } 
    ], 
"ResponseCode":0, 
"Status":"OK", 
"Error":"None" 
} 

oder

{ 
    "Result": 
    { 
     "Id":24379, 
     "AccountName":"foo" 
    }, 
    "ResponseCode":0, 
    "Status":"OK", 
    "Error":"None" 
} 

Sosometimes „Ergebnis“ ist ein Array von Ergebnissen oder „Ergebnis“ könnte eine einzige Antwort sein.

Ich habe versucht, mit der Antwort von How to handle both a single item and an array for the same property using JSON.net, aber ich bekomme immer noch Fehler.

Insbesondere Ich bin ein schaut

Newtonsoft.json.jsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List'... 

Individuelle Konverter bekommen wie:

public class SingleOrArrayConverter<T> : JsonConverter 
    { 
     public override bool CanConvert(Type objecType) 
     { 
      return (objecType == typeof(List<T>)); 
     } 

     public override object ReadJson(JsonReader reader, Type objecType, object existingValue, 
      JsonSerializer serializer) 
     { 
      JToken token = JToken.Load(reader); 
      if (token.Type == JTokenType.Array) 
      { 
       return token.ToObject<List<T>>(); 
      } 
      return new List<T> { token.ToObject<T>() }; 
     } 

     public override bool CanWrite 
     { 
      get { return false; } 
     } 

     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

Meine Antwort Klasse (n) aussehen

public class TestResponse 
    { 
     [JsonProperty("Result")] 
     [JsonConverter(typeof(SingleOrArrayConverter<string>))] 
     public List<DeserializedResult> Result { get; set; } 
    } 
public class DeserializedResult 
    { 
     public string Id { get; set; } 
     public string AccountName { get; set; } 
    } 

Und schließlich sieht meine Anfrage wie

List<TestResponse> list = JsonConvert.DeserializeObject<List<TestResponse>>(response.Content); 
+0

Haben Sie nur zwei Arten von Antworten? –

+0

Sie werden immer nur eines dieser beiden Formate folgen, obwohl der Inhalt natürlich anders sein wird. Manchmal hat "Ergebnis" mehrere Felder, manchmal nur ein oder zwei, unabhängig davon, ob es ein einzelnes Objekt oder ein Array von bis zu 100 Objekten zurückgibt. – gilliduck

+0

Jetzt werde ich versuchen, eine Code-Lösung zu schreiben. –

Antwort

4

Der Code ist in Ordnung, es braucht nur ein paar Art zwickt.

Diese Linie

List<TestResponse> list = JsonConvert.DeserializeObject<List<TestResponse>>(response.Content); 

Bedürfnisse so sein, denn Ihre Antwort ein object, kein List.

TestResponse list = JsonConvert.DeserializeObject<TestResponse>(response); 

dann Ihre benutzerdefinierten Deserializer Attribut:

[JsonConverter(typeof(SingleOrArrayConverter<string>))] 

Bedürfnisse zu werden:

[JsonConverter(typeof(SingleOrArrayConverter<DeserializedResult>))] 

weil Ihr Result Objekt kein string ist oder ein Array von string s, es ist entweder ein Array von DeserializedResult s oder DeserializedResult.

+1

Ich schulde dir ein Bier (oder was auch immer du trinkst). Ich gebe mir selbst das Gefühl, dass es so etwas wie kleine Verbesserungen war, um es zum Laufen zu bringen. Tausend Dank! – gilliduck

0

Ich denke, dass es keine Möglichkeit gibt, zu unterscheiden, welche Art von Antwort haben Sie wegen Desirialisierung. Das ist, warum ich vorschlagen manualy Art von Antwort zu überprüfen:

using System; 
using System.Collections.Generic; 
using Newtonsoft.Json; 

namespace TestConsoleApp 
{ 
    public class Class1 
    { 

     public class Result 
     { 
      public int Id { get; set; } 
      public string AccountName { get; set; } 
     } 

     public class ModelWithArray 
     { 
      public int TotalRecords { get; set; } 
      public List<Result> Result { get; set; } 
      public int ResponseCode { get; set; } 
      public string Status { get; set; } 
      public string Error { get; set; } 
     } 

     public class Result2 
     { 
      public int Id { get; set; } 
      public string AccountName { get; set; } 
     } 

     public class ModelWithoutArray 
     { 
      public Result2 Result { get; set; } 
      public int ResponseCode { get; set; } 
      public string Status { get; set; } 
      public string Error { get; set; } 
     } 

     public static void Main(params string[] args) 
     { 
      //string json = "{\"TotalRecords\":2,\"Result\":[{\"Id\":24379,\"AccountName\":\"foo\"},{\"Id\":37209,\"AccountName\":\"bar\"}], \"ResponseCode\":0,\"Status\":\"OK\",\"Error\":\"None\"}"; 
      string json = "{\"Result\":{\"Id\":24379,\"AccountName\":\"foo\"},\"ResponseCode\":0,\"Status\":\"OK\",\"Error\":\"None\"}"; 

      if (checkIsArray(json)) 
      { 
       ModelWithArray data = JsonConver.DeserializeObject<ModelWithArray >(json); 
      }else 
      { 
       ModelWithoutArray data = JsonConver.DeserializeObject<ModelWithoutArray>(json); 
      } 

     } 

     static bool checkIsArray(string json) 
     { 

      Dictionary<string, object> desData = JsonConvert.DeserializeObject<Dictionary<string, object>>(json); 

      if (desData["Result"].GetType().Name.Contains("Array")) 
      { 
       return true; 
      } 
      else 
      { 
       return false; 
      } 

     } 

    } 
} 
+0

'Ich schlage vor, manuelle Art der Antwort zu überprüfen '. Sie müssen nicht, das Paket 'newtonsoft.json' bietet Möglichkeiten, dies zu vermeiden. –

+0

Hmm. Ich wusste nicht ... –

Verwandte Themen