C# 가상 클래스 JSON 직렬화/역직렬화

jody·2024년 5월 28일

코딩메모

목록 보기
4/7

참고: https://learn.microsoft.com/ko-kr/dotnet/standard/serialization/system-text-json/polymorphism?pivots=dotnet-8-0
가상 클래스, 상속 클래스... 명칭에 아직 익숙하지 않다.

기존에는 JsonConvert.SerializeObject 를 썼는데 클래스의 타입을 자동으로 표기하는 기능을 사용하려면 JsonSerializer.Serialize 를 써야한다.
역직렬화를 할 때도 마찬가지로 JsonSerializer.Deserialize 를 사용한다

base 클래스와 derived 클래스를 구분할 수 있도록 다형 형식 판별자(Polymorphic type discriminators)를 써준다.

[JsonDerivedType(typeof(SampleBase), typeDiscriminator: "base")]
[JsonDerivedType(typeof(SampleDerived), typeDiscriminator: "Derived")]
public class SampleBase
{
    public string strBase = "base";
}

public class SampleDerived : SampleBase
{
    public string strDerived = "derived";
}

직렬화

SampleDerived newDer = new SampleDerived();
// 오브젝트에 내용을 채워넣는다
JsonSerializerOptions jsonOptions = new JsonSerializerOptions
{
	IncludeFields = true //클래스의 모든 public을 json에 포함
};
string sJson = JsonSerializer.Serialize(newDer, jsonOptions);
File.WriteAllText(filePath, resultData);

(옵션의 경우 클래스의 멤버 변수에 일일히 [JsonInclude] 를 넣어줄 수도 있다)

public class SampleDerived : SampleBase
{
    [JsonInclude] public string strDerived = "derived";
}

결과: (테스트 해보지는 않았음)

  {
    "$type": "Derived",
    "strDerived": "derived",
    "strBase": "base"
  }

역직렬화

string sJson;
//json 파일을 문자열로 불러온다
JsonSerializerOptions jsonOptions = new JsonSerializerOptions
{
	IncludeFields = true //이 옵션을 넣어줘야 값을 불러온다
};
SampleBase loadData = JsonSerializer.Deserialize<SampleBase>(sJson, jsonOptions);

결과를 확인하면 "$type": "Derived" 항목에 의해 SampleDerived 오브젝트로 생성되었음을 알 수 있다.

추가 json 참고 사항

실제로 개발할 때는 Base와 Derived가 섞인 리스트를 직렬화, 역직렬화 했고 잘 되었다.

string sJson = LoadJsonFile();
List<SampleBase> loadList = JsonSerializer.Deserialize<List<SampleBase>>(sJson, jsonOptions);

이런식으로..

json 옵션의 경우 저장하거나 로드할 때 마다 일일히 생성하지 않고 아예 하나 만들어서 써줬다

public JsonSerializerOptions jsonOptions = new JsonSerializerOptions
{
	Encoder = JavaScriptEncoder.Create(UnicodeRanges.BasicLatin, UnicodeRanges.HangulSyllables), //한글 인코딩
	WriteIndented = true, //띄어쓰기
	IncludeFields = true //클래스의 모든 퍼블릭 멤버변수 포함
};

0개의 댓글