[TIL] C# - 직렬화 & 역직렬화 (1)

MINO·2024년 4월 25일
0
post-thumbnail

2024-04-25

개인 프로젝트의 마감일이다.
마지막 기능인 "데이터 저장하기" 라는 큰 벽을 만나게 되었다.
json 을 활용하여 게임을 종료해도 이전에 플레이 한 데이터가 남도록 만들어보자.

최소 하루 한 번, 영타를 연습하면 좋을 것 같아 하루 루틴에 추가하였다.

직렬화 (Serialize)

객체를 다른 형식으로 변환하여 데이터를 저장하거나 전송하는 과정이다.
(C# 의 경우, 주로 데이터를 텍스트의 형식으로 변환하여 데이터를 전송, 특히 Json 형태로)

건담 프라모델(클래스)을 분해하여(직렬화) 내용물과 조립설명서로 택배 (json)를 보냄

  • Json (JavaScript Object Notation) : 자바 스크립트에서 데이터를 저장하거나 전송할 때 많이 사용하는 Data 교환 형식

목적

  • 데이터 저장 : 객체의 현재 상태를 저장, 저장된 데이터를 다시 읽어와서 사용

    • 게임이 종료되어도 다시 실행했을 때, 유저의 정보를 가져오기 위해
  • 데이터 전송 : 네트워크를 통해서 다른 시스템으로 전송하거나 통신

    • 채팅 시스템을 만들 때, 유저 간의 텍스트를 주고 받을 때
  • 복원 및 복구 : 프로그램이 중단됐을 때, 객체의 이전 상태를 복원하거나 복구


JSON.NET

닷넷에서 JSON 을 사용하기 위한 오픈 소스 중 하나이다.

아래의 이미지를 따라 Newtonsoft.Json 패키지를 설치하고, 코드에 using Newtonsoft.Json 을 추가한다.

JsonConvert 를 입력하고 빨간줄에 마우스를 올려 다음과 같이 진행한다.


직렬화에 사용되는 함수

진행한 게임 정보를 저장하기 위해서 Serialize 를 수행하여
Player 클래스 정보를 Json 형식으로 전환하는 것이 목표이다.

먼저 사용되는 함수를 알아보자.


Environment.GetFolderPath( )

지정된 시스템 특수 폴더의 경로를 가져온다.

public static string GetFolderPath(Environment.SpeicalFolder folder);

매개 변수 : folder - Environment.SpeicalFolder (시스템 관련 폴더를 식별하는 열거형 값 중 하나)

반환 값 : String

  • 해당 폴더가 실제 컴퓨터에 존재하면, 지정한 시스템 특수 폴더의 경로가 String 형태로 저장

  • 존재하지 않는다면, 빈 문자열("")을 저장


Path.Combine( )

두 문자열을 한 경로로 결합한다.

public static string Combine(string path1, string path2);

매개 변수 : path 1,2 (결합할 경로들)

반환 값 : String

  • 결합된 경로. 만약 지정된 경로 중 하나의 길이가 0인 문자열이면, 다른 경로를 반환

  • path2 에 절대 경로가 포함되어 있으면 path2 를 반환


JsonConvert.SerializeObject( )

.NET 객체로부터 JSON 문자열을 만들기 위해 사용한다.

위의 함수들과는 다르게 패키지를 추가하여 사용한 메서드이기 때문에
함수를 클릭하고 F12 버튼을 눌러 정의를 확인할 수 있었다.

매개 변수 : value (Json 으로 변환시킬 객체) , converters(직렬화 되는 동안 사용되는 변환기 모음)

반환 값 : String

  • 객체의 Json 문자열 표현

File.WriteAllText( )

새 파일을 만들고 지정된 문자열을 파일에 쓴 다음 파일을 닫는다.
파일이 이미 존재하면, 덮어쓴다.

public static void WriteAllText(string path, string? contents);

매개 변수 : path (쓸 파일) , contents (파일에 쓸 문자열)


예시 코드

static void SaveData()
{
	// 저장할 json 파일의 이름 지정
    string playerDataName = "playerStatData.json";
    string itemDataName = "itemData.json";
    
    // 데이터 경로 저장 (C드라이브 - Documents)
    string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
    
    // 여러 문자열을 한 경로로 결합하는 Path.Combine(str1, str2)
    string playerDataPath = Path.Combine(path, playerDataName);
    string itemDataPath = Path.Combine(path, itemDataName);

	// Class 를 Json 으로 Serialize (직렬화)
    string playerJson = JsonConvert.SerializeObject(player, Formatting.Indented);
    string itemJson = JsonConvert.SerializeObject(player.myItems, Formatting.Indented);
    
    // 새 파일을 만들고 파일에 내용을 쓴 다음 닫는다. 대상 파일이 이미 존재하는 경우 덮어쓴다.
    File.WriteAllText(playerDataPath, playerJson);
    File.WriteAllText(itemDataPath, itemJson);

}

역직렬화 (Deserialize)

직렬화의 반대 과정.
직렬화된 데이터를 원래 데이터 구조로 복원하는 작업

택배 (json) 를 받아 내용물과 조립설명서를 통해 조립하여 건담 (클래스)을 복구


목적

  • 데이터 복원 : 텍스트를 다시 클래스로 변환
  • 데이터 읽기 : 네트워크로 전송된 데이터를 프로그램이 읽을 수 있는 형태로 변환
  • 데이터 공유 : 다른 시스템과 데이터를 공유하고 객체를 전달
string noviceArmor = "수련자 갑옷";
string info = "수련에 도움을 주는 갑옷입니다.";
int price = 1000;
Console.WriteLine("{0} | {1} | {2} G", noviceArmor ,info, price};
// 결과 : 수련자 갑옷 | 수련에 도움을 주는 갑옷입니다. | 1000 G

역직렬화에 사용되는 함수

저장한 Json 형식을 불러와 객체 정보로 전환하는 것이 목표이다.

직렬화에 사용되는 함수와 유사하다.


File.Exists( )

지정된 파일이 있는지 확인한다.

public static bool Exists(string? path);

매개 변수 : path (확인할 파일)

반환 값 : Boolean

  • 파일의 이름이 존재하고, 호출자에게 필요한 권한이 있으면 true , 그렇지 않으면 false

  • path 가 잘못된 경로이거나 빈 문자열이면 false

  • 호출자에게 지정된 파일을 읽을 권한이 없는 경우 false


File.ReadAllText( )

텍스트 파일을 열고 파일의 모든 텍스트를 읽은 다음 파일을 닫는다.

public static string ReadAllText(string path);

매개 변수 : path (읽어올 파일의 경로)

반환 값 : String

  • 파일의 모든 텍스트를 포함하는 문자열


JsonConvert.DeserializeObject( )

JSON 문자열로부터 .NET 객체를 만들기 위해 사용한다.

위의 함수들과는 다르게 패키지를 추가하여 사용한 메서드이기 때문에
함수를 클릭하고 F12 버튼을 눌러 정의를 확인할 수 있었다.

매개 변수 : value (객체로 변환시킬 Json 문자열)

반환 값 : T (클래스)

  • Json 이 저장하고 있던 객체의 정보를 반환

예시 코드

static void LoadData()
{
	// 불러올 json 파일의 이름 지정
    string playerDataName = "playerStatData.json";
    string itemDataName = "itemData.json";

    // 데이터 경로 지정 (C 드라이브 - Documents)
    string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

    string playerDataPath = Path.Combine(path, playerDataName);

    if(File.Exists(playerDataPath)) // json 파일이 존재
    {
        string playerJson = File.ReadAllText(playerDataPath);
        player = JsonConvert.DeserializeObject<Player>(playerJson);
        Console.WriteLine("플레이어 데이터를 불러왔습니다.");
    }
    else // json 파일이 존재하지 않음
    {
        Console.WriteLine("저장된 플레이어 데이터가 없습니다.");
    }

}

결과물

"동물의 숲" 게임의 경우, 하루를 마무리하고 침대에 누워 휴식을 취할 때, 게임 정보가 저장된다.
이를 떠올려, [휴식하기] 를 통해 데이터의 정보를 저장하도록 설정하였고,
게임이 시작될 때, 저장된 정보가 있는지 확인하여 불러오도록 했다.


1. 데이터 저장

저장

2. 정상적으로 저장된 json 파일들


3. 데이터 불러오기

불러오기(파일X)불러오기(파일O)

TIL 마무리

어제 계획한 대로, 모든 기능 구현을 마쳤다.

마감 기한까지 시간도 넉넉하여
미처 발견하지 못한 예외 케이스나 버그
(골드가 부족할 때, 메시지를 출력하자마자 바로 화면이 전환되는 경우 -> 발견 후 수정)
조금 더 최적화할 수 있는 코드는 없는지
(3중 if문을 && 와 || 연산자를 적절히 사용해서 줄이기)
찾아보는 시간을 가지며

첫번째 개인 과제 프로젝트를 마칠 수 있었다.

profile
안녕하세요 게임 개발하는 MINO 입니다.

0개의 댓글