이번 글에 대한 제목을 정하기가 어렵네요.

상황 설명을 해보자면 DB테이블에 nvarchar 타입에 json 포맷으로 된 값이 있고 이 값을 API로 전달해주면 됩니다.

리턴되는 데이터는 아래와 같습니다.


 "{ \"Key\": 1 " }"

리턴되는 타입이 string이고 그 안에 키 또는 string 값에 "문자를 필요로 하기 때문에 \문자로 string안에 string을 구분해주고 있는 것입니다.

이렇게 리턴을 하였을 경우에도 JSON.NET에서는 클래스(object)로 역직렬화가 가능합니다. 하지만 다른 언어의 다른 json 직렬화 라이브러리의 경우에는 에러가 발생하기도 하며 API 명세서에 노출하기에도 깔끔하지 못해보입니다.


최초 DB에서 받아오는 json string에 대해서 클래스(object)를 만들면 간단하게 해결됩니다. 하지만 여기서는 json string에 대한 포맷이 주기적으로 변경될 수도 있고 그에 따른 변경사항에 대해서 약결합을 만들어야 하는 상황입니다.

다음으로 생각해볼 수 있는 건 API에서 string이 아닌 타입으로 넘기면 되지 않을까 싶었고 검색을 해보았습니다.


https://stackoverflow.com/questions/22906010/deserialize-dynamic-json-string-using-newtonsoft-json-net


ExpandoObject 라는 System.Dynamic 네임스페이스의 클래스가 있었네요. JSON.NET으로 아래와 같이 역직렬화를 해주고 있습니다.


var converter = new ExpandoObjectConverter();

dynamic obj = JsonConvert.DeserializeObject<ExpandoObject>(string, converter);

=> JSON.NET에서 ExpandoObjectConverter를 제공해주고 있습니다. 해결은 아주 간단하게 되었고 ExpandoObject를 살펴보니 IDictionary<string, object>를 상속받고 있습니다. 아하~ json string을 아래처럼 Dictionary로 만들어주고 리턴을 해도 되겠군요.


Dictionary<string object> dic = new Dictionary<string object>();

dic.Add("Key", 1);

=> 그렇다면 Dictionary가 아닌 ExpandoObject 사용하는 것에 대한 장점은 무엇일까요?

1. 복잡한 json string일 경우(특히 계층 관계)

2. ExpandoObject가 INotifyPropertyChanged 인터페이스를 상속받고 있는 걸로 봐서는 프로퍼티 변경에 대한 통지(알림)를 받을 수 있네요

3. 이벤트도 추가할 수 있습니다.


해결은 간단하게 되었고 직렬화에 대한 이해도 살짝 올라갔네요. ㅎㅎ

Posted by resisa