2017-05-21 24 views
3

私はNewtonsoft.Jsonを使用して、返されてくるJSONデータを処理しています。だから、時には「結果は」結果の配列または「結果」は、単一の応答可能性があるJSON単一オブジェクトと配列の処理

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

または

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

:私はバックのように見える何かを得ることができますいずれかの要求内容に応じて。

私はHow to handle both a single item and an array for the same property using JSON.netの答えを使ってみましたが、まだエラーが発生します。特に

私は

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

カスタムコンバータを取得していますと、次のようになります。

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(); 
     } 
    } 

私の応答クラス(ES)最後に

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

そして、私の要求ルックスのように見えますlike

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

答えは2種類だけですか? –

+0

コンテンツは明らかに異なっていますが、これらの2つのフォーマットのうちの1つに従うことになります。時には「結果」には、単一のオブジェクトまたは100個までのオブジェクトの配列を返すかどうかにかかわらず、複数のフィールドがあります。 – gilliduck

+0

今、コードソリューションを作成しようとします。 –

答えて

4

あなたのコードは問題ありません。ちょっとした調整が必要です。

このライン

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

あなたの応答がobject、ないListあるので、このようにする必要があります。

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

その後、カスタムデシリアライザ属性:

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

はなっている必要があります

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

あなたResultオブジェクトがstringまたはstringの配列ではないので、それはどちらかの配列ですDeserializedResultまたはDeserializedResultである。

+1

私はあなたにビール(またはあなたが飲むもの)を借りています。私はそれが働くようにマイナーな微調整のようなものだと自分自身を蹴っている。多大なる感謝! – gilliduck

0

私は、あなたがどのようなタイプのレスポンスを推奨しているのか分からないと思います。それで私は手動の応答のタイプをチェックすることを提案する理由:

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

'私は手動のタイプの応答をチェックすることを提案する'。あなたがする必要はありません、パッケージ 'newtonsoft.json'はこれを回避する方法を提供します。 –

+0

Hmm。私は知らなかった... –

関連する問題