[Unity] JSON 직렬화/역직렬화(2)

muchan
muchan
∙∙조회 10

1편

[Unity] JSON 직렬화 / 역직렬화(1)

Newtowsoft.Json

라이브러리 소개

  • Newtonsoft.Json (Json.Net)은 C#에서 가장 널리 사용되는 JSON 라이브러리
  • Unity 패키지 매니저에서 com.unity.nuget.newtonsoft-json으로 제공됨

핵심 기능:

  • C# 객체를 JSON 문자열로 변환 (직렬화, Serialization)
  • JSON 문자열을 C# 객체로 변환 (역직렬화, Deserialization)
Mermaid
렌더링 중...

직렬화: C# 객체를 JSON 문자열로 변환
역직렬화: JSON 문자열을 C# 객체로 변환

Formatting 설정

Formatting.None: 한 줄로 출력 (파일 크기가 작다)
Formatting.Indented: 들여쓰기와 줄바꿈 적용 (사람이 읽기 편하다)

JsonSerializerSettings

직렬화/역직렬화의 동작을 세밀하게 제어하는 설정 객체

csharp
var settings = new JsonSerializerSettings()
{
    Formatting = Formatting.Indented,
    TypeNameHandling = TypeNameHandling.All,
};

// settings를 전달하여 직렬화/역직렬화
var json = JsonConvert.SerializeObject(obj, settings);
var obj = JsonConvert.DeserializeObject<SaveData>(json, settings);

주요 설정

설정설명
FormattingIndented: 들여쓰기 / None: 한 줄 출력
TypeNameHandling직렬화 시 타입 정보 포함 여부
NullValueHandlingnull 값 처리 방식

TypeNameHandling

JSON에 C# 타입 정보를 포함시키는 설정임. 다형성(상속)이 있는 객체를 역직렬화할 때 원래 타입을 복원하기 위해 필요함

TypeNameHandling설명
None타입 정보 포함하지 않음 (기본값)
All모든 타입에 $type 추가
Auto선언 타입과 실제 타입이 다를 때만 추가

JsonConverter - 커스텀 직렬화

왜 필요한가?

기본 직렬화 방식이 맞지 않는 경우가 있음:

  • Unity의 Vector3: 내부 프로퍼티가 많아 불필요한 데이터가 직렬화됨
  • 참조 데이터: 객체 전체를 저장하지 않고 Id만 저장하고 싶음
  • 재활용하면서 사용할 수 있다

대표적인 오류 메시지: JsonSerializationException: Self referencing loop detected for property 'normalized' with type

방법

  1. JsonConverter를 상속받고
  2. WriteJson을 먼저 작성하고
  3. ReadJson을 작성한다

Write와 Read 작성 순서는 상관없지만 Write를 먼저 작성하는게 개인적으로 순서가 맞는 느낌이다.
(일단 먼저 써놔야 읽을 수 있다는 개인적인 생각)

JObject

  • ReadJson에서 JObject를 사용하여 JSON을 유연하게 파싱할 수 있다
  • JSON 객체를 Dictionary처럼 키로 접근할 수 있게 해주는 클래스이다.

컨버터 적용 방법

커스텀 컨버터를 적용하는 3가지 방법:

방법코드적용 범위
메서드 인자 전달JsonConvert.SerializeObject(obj, new MyConverter())해당 호출에서만
[JsonConverter] 어트리뷰트필드/클래스 선언부에 부착해당 필드/클래스에 항상
Settings.Converterssettings.Converters.Add(new MyConverter())설정을 사용하는 모든 호출

3가지 중 하나 사용하면 된다

csharp
// 방법 1: 메서드 인자로 전달
string json = JsonConvert.SerializeObject(obj, Formatting.Indented, new Vector3Converter());
var obj = JsonConvert.DeserializeObject<PlayerState>(json, new Vector3Converter());

// 방법 2: 어트리뷰트
public class SaveItemData
{
    [JsonConverter(typeof(ItemDataConverter))]
    public ItemData itemData;
}

// 방법 3: Settings에 추가
var settings = new JsonSerializerSettings();
settings.Converters.Add(new Vector3Converter());
string json = JsonConvert.SerializeObject(obj, settings);

개인적으로 3번이 제일 편한 것 같다