2017-05-21 2 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(); 
     } 
    } 

내 응답 클래스 (들) 마지막으로

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

두 가지 답변 만 있습니까? –

+0

그들은 두 가지 형식 중 하나만을 따르 겠지만 내용은 분명히 다릅니다. 때로는 "결과"에는 단일 객체 또는 최대 100 개의 객체 배열을 반환하는지 여부와 상관없이 여러 번 또는 여러 번 필드가 하나씩 포함됩니다. – gilliduck

+0

이제 코드 솔루션을 작성하려고합니다. –

답변

4

코드는 괜찮습니다. 단지 몇 가지 유형 조정이 필요합니다. 당신의 응답이 object 아닌 List 때문에

이 줄

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

요구는, 다음과 같이합니다.

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

그런 다음 사용자 정의 디시리얼라이저 속성 :

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

필요가되기 위해 :

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

당신의 Result 객체가 아닌 때문에이 또는 string의 배열, 그것은 두 배열의 stringDeserializedResult 또는 DeserializedResult입니다.

+1

나는 당신에게 맥주 (또는 당신이 마시는 것)를 빚지고있다. 나는 그것이 작동하도록 사소한 비틀기와 같은 것이었다라고 나 자신에게 차고있다. 천 가지 고마워! – gilliduck

0

내가 생각하기에, 어떤 유형의 응답을 당신이 desirialization 할 것인지에 대해서는 언급 할 방법이 없다고 생각합니다. 그 이유는 내가 수동 유형의 응답을 확인하는 것이 좋습니다 :

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

흠. 나는 몰랐다. ... –