공공데이터 API 수집 하고 있는 중에

JSON 데이터 매개변수 중 하나가 단일 또는 배열이 나오는 경우를 경험하게 되었다.

아래 이미지에서 items 매개변수를 보면 경우의 따라 단일 또는 배열로 데이터를 리턴하고 있는 것을

확인 할 수 있다;;

 

 

 

기존 item 배열 기준으로 직렬화 하기 위해 작성 한 타입 때문에

데이터 수집 과정 중 단일 객체가 나올경우 직렬화 과정에서 에러가 나기 시작했다.

 

아래 코드는 JSON 데이터중 객체의 타입이 단일 또는 배열 함께 처리 될 수 있도록

item 필드에 커스텀 어트리뷰트 작성 하여 올바르게 직렬화 할 수 있도록 처리 한다.

작성하는 부분을 스택 오버플로 기사 에서 차용했다 .

 

확인

public class SingleOrArrayConverter<T> : JsonConverter
{
  public override object ReadJson(JsonReader reader, Type objectType, 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 class Items
{
	[JsonConverter(typeof(SingleOrArrayConverter<Item>))]
	public List<Item> item { get;set;}
}

JsonConverter 추상 메서드 ReadJson에서
객체의 type 확인 하여 ToObject<List<T>> 또는 ToObject<T> 리턴 타입 여부를 결정 한다.

 

전체코드

public class TradeData
{
	public Response response { get; set; }
}
public class Response
{
	public Header header { get; set; }
	public Body body { get; set; }
}
public class Header
{
	public string resultCode { get; set; }
	public string resultMsg { get; set; }
}
public class Body
{
	public Items items { get; set; }
	public int numOfRows { get; set; }
	public int pageNo { get; set; }
	public int totalCount { get; set; }
}
public class Items
{
	[JsonConverter(typeof(SingleOrArrayConverter<Item>))]
	public List<Item> item { get;set;}
}
//-----------------------------------------------------------------------------//
//-----------------------------------------------------------------------------//


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

    public override object ReadJson(JsonReader reader, Type objectType, 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 void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        List<T> list = (List<T>)value;
        if (list.Count == 1)
        {
            value = list[0];
        }
        serializer.Serialize(writer, value);
    }

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

 

'C#' 카테고리의 다른 글

ADO.NET vs an ORM (Dapper & EF)  (0) 2021.10.13
C# Task WaitAll 와 WhenAll  (0) 2021.09.16
C# 정규식을 활용한 계좌번호 ,휴대폰 번호 마스킹 처리.  (0) 2021.09.08
c# Entity Framework  (0) 2021.08.29
[C#] Garbage Collection  (0) 2021.07.08

+ Recent posts