728x90
기존 저장방법
c# 데이터 저장 <Newtonsoft.Json 활용>
0. 저장할 클래스 설정 class Player { // public으로 선언해 줘야 데이터 저장 및 불러오기가 가능하다 public int Hp { get; set; } public int Attack { get; set; } public int Defense { get; set; } public Player(int hp, int attack, i
rimugiri.tistory.com
문제
Interface의 경우 데이터를 불러 올 상황에 JsonConvert 오류가 발생하게 된다.
따라서 이를 해결하기 위한 방안을 소개한다.
0. 데이터 저장 클래스
▶ 예제 클래스 및 인터페이스 선언
class Player
{
public string Name { get; set; }
public float Hp { get; set; }
public float Attack { get; set; }
public int Defense { get; set; }
public List<IItem> itemList = new List<IItem>();
public Player(string _name, float _hp, float _attack, int _defense)
{
Name = _name;
Hp = _hp;
Attack = _attack;
Defense = _defense;
}
}
interface IItem
{
public string Name { get; set; }
public string Description { get; set; }
ItemType Type { get; }
public string ItemInfo();
}
class Weapon : IItem
{
public string Name { get; set; }
public string Description { get; set; }
// 이 변수를 통해 어떤 클래스 인지 확인
public ItemType Type => ItemType.Weapon;
public int Attack { get; set; }
public Weapon(string _name, string _description, int _attack)
{
Name = _name;
Description = _description;
Attack = _attack;
}
public string ItemInfo()
{
return $"이름 : {Name} | 공격력 {Attack} | {Description}";
}
}
class Shield : IItem
{
public string Name { get; set; }
public string Description { get; set; }
// 이 변수를 통해 어떤 클래스 인지 확인
public ItemType Type => ItemType.Shield;
public int Defense { get; set; }
public Shield(string _name, string _description, int _defense)
{
Name = _name;
Description = _description;
Defense = _defense;
}
public string ItemInfo()
{
return $"이름 : {Name} | 방어력 {Defense} | {Description}";
}
}
enum ItemType
{
Weapon,
Shield
}
1. 사용자 정의 JsonConverter 정의
▶ 클릭 하세요
public class ItemJsonConverter : JsonConverter
{
// IItem 타입인 경우에만 이 Converter 적용
public override bool CanConvert(Type objectType)
{
return objectType == typeof(IItem);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject item = JObject.Load(reader);
// class에서 정의한 ItemType를 통한 class 종류 확인
ItemType itemType = item["Type"].ToObject<ItemType>();
// IItem을 상속받은 class 타입별 변환
switch (itemType)
{
case ItemType.Weapon:
return item.ToObject<Weapon>();
case ItemType.Shield:
return item.ToObject<Shield>();
}
return null;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
}
2. interface list 포함 데이터 저장
▶ 클릭 하세요
void SaveData(Player player)
{
string FilePath = ""; // 파일경로설정
try
{
string json = JsonConvert.SerializeObject(player, Formatting.Indented, new JsonSerializerSettings
{
// interface를 담고있는 리스트를 저장하기 위한 사용자 정의 Converter
Converters = new List<JsonConverter> { new ItemJsonConverter() }
});
File.WriteAllText(FilePath, json);
}
catch (Exception ex)
{
Console.WriteLine($"Error saving data: {ex.Message}");
}
}
3. interface 포함 데이터 불러오기
▶ 클릭 하세요
Player LoadData()
{
string FilePath = ""; // 파일경로설정
try
{
if (File.Exists(FilePath))
{
string json = File.ReadAllText(FilePath);
return JsonConvert.DeserializeObject<Player>(json, new JsonSerializerSettings
{
Converters = new List<JsonConverter> { new ItemJsonConverter() }
});
}
else
{
return new Player("BraveSoldier", 200, 20, 5);
}
}
catch (Exception ex)
{
Console.WriteLine($"Error Load data: {ex.Message}");
return new Player("BraveSoldier", 200, 20, 5);
}
}
4.예제
▶ 클릭 하세요
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace MyApp // Note: actual namespace depends on the project name.
{
class Program
{
static void Main(string[] args)
{
// 데이터 저장 예제
// Player player = new Player("BraveSoldier", 300, 30, 10);
// player.itemList.Add(new Weapon("검", "검이다", 10));
// player.itemList.Add(new Shield("방패", "방패이다", 10));
// Console.WriteLine(player.itemList[0].ItemInfo());
// Console.WriteLine(player.itemList[1].ItemInfo());
// Console.WriteLine($"Hp : {player.Hp}\nAttack : {player.Attack}\nDefense : {player.Defense}");
// SaveData(player);
// 데이터 불러오기 예제
Player player = LoadData();
Console.WriteLine(player.itemList[0].ItemInfo());
Console.WriteLine(player.itemList[1].ItemInfo());
Console.WriteLine($"Hp : {player.Hp}\nAttack : {player.Attack}\nDefense : {player.Defense}");
}
static void SaveData(Player player)
{
string FilePath = "../../../PlayerData.json"; // 파일경로설정
try
{
string json = JsonConvert.SerializeObject(player, Newtonsoft.Json.Formatting.Indented, new JsonSerializerSettings
{
// interface를 담고있는 리스트를 저장하기 위한 사용자 정의 Converter
Converters = new List<JsonConverter> { new ItemJsonConverter() }
});
File.WriteAllText(FilePath, json);
}
catch (Exception ex)
{
Console.WriteLine($"Error saving data: {ex.Message}");
}
}
static Player LoadData()
{
string FilePath = "../../../PlayerData.json"; // 파일경로설정
try
{
if (File.Exists(FilePath))
{
string json = File.ReadAllText(FilePath);
return JsonConvert.DeserializeObject<Player>(json, new JsonSerializerSettings
{
Converters = new List<JsonConverter> { new ItemJsonConverter() }
});
}
else
{
return new Player("BraveSoldier", 200, 20, 5);
}
}
catch (Exception ex)
{
Console.WriteLine($"Error Load data: {ex.Message}");
return new Player("BraveSoldier", 200, 20, 5);
}
}
}
class Player
{
public string Name { get; set; }
public float Hp { get; set; }
public float Attack { get; set; }
public int Defense { get; set; }
public List<IItem> itemList = new List<IItem>();
public Player(string _name, float _hp, float _attack, int _defense)
{
Name = _name;
Hp = _hp;
Attack = _attack;
Defense = _defense;
}
}
interface IItem
{
public string Name { get; set; }
public string Description { get; set; }
ItemType Type { get; }
public string ItemInfo();
}
class Weapon : IItem
{
public string Name { get; set; }
public string Description { get; set; }
public ItemType Type => ItemType.Weapon;
public int Attack { get; set; }
public Weapon(string _name, string _description, int _attack)
{
Name = _name;
Description = _description;
Attack = _attack;
}
public string ItemInfo()
{
return $"이름 : {Name} | 공격력 {Attack} | {Description}";
}
}
class Shield : IItem
{
public string Name { get; set; }
public string Description { get; set; }
public ItemType Type => ItemType.Shield;
public int Defense { get; set; }
public Shield(string _name, string _description, int _defense)
{
Name = _name;
Description = _description;
Defense = _defense;
}
public string ItemInfo()
{
return $"이름 : {Name} | 방어력 {Defense} | {Description}";
}
}
enum ItemType
{
Weapon,
Shield
}
public class ItemJsonConverter : JsonConverter
{
// IItem 타입인 경우에만 이 Converter 적용
public override bool CanConvert(Type objectType)
{
return objectType == typeof(IItem);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject item = JObject.Load(reader);
// class에서 정의한 ItemType를 통한 class 종류 확인
ItemType itemType = item["Type"].ToObject<ItemType>();
// IItem을 상속받은 class 타입별 변환
switch (itemType)
{
case ItemType.Weapon:
return item.ToObject<Weapon>();
case ItemType.Shield:
return item.ToObject<Shield>();
}
return null;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
}
}
728x90
'언어 정리 > c#' 카테고리의 다른 글
c# 2차원 배열 정렬 방법 (0) | 2024.01.15 |
---|---|
c# int[,]와 int[][]의 차이점 (0) | 2024.01.11 |
c# 데이터 저장 <Newtonsoft.Json 활용> (0) | 2024.01.07 |
[c#] Console 다룰 때 알아두면 좋은 기능 (1) | 2024.01.06 |
LeetCode - 300(동적 프로그래밍) (1) | 2024.01.02 |