참고: 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 오브젝트로 생성되었음을 알 수 있다.
실제로 개발할 때는 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 //클래스의 모든 퍼블릭 멤버변수 포함
};