해당 글은 Csv를 Json으로 변환하는 툴에 대한 가이드입니다.

자세한 코드 내용은 아래의 블로그를 참고해 주세요 

2025.02.25 - [Unity] - [Unity] Csv To Json 변환 툴

 

[Unity] Csv To Json 변환 툴

내일배움캠프-레벨업세션에서 엑셀 파일을 Json으로 변환하는 기능을 봤는데 이번 프로젝트에서 그대로 사용하기에는 맞지않다고 느껴서유니티 내부에서 csv파일을 Json으로 저장하는 기능을 만

youcheachae.tistory.com

 


Csv 변환 방법                                                                                       

  1. wrapper 클래스를 작성합니다
    1. 클래스는 반드시 ICsvParsable 인터페이스를 상속받아 구현해야 합니다.
    2. Parse(string [] values) 메서드 구현
      1. CSV 파일의 각 행은 values 배열로 전달됩니다(string 타입).
      2. 클래스의 필드명에 맞춰서 형변환이 필요합니다
        1. 구체적인 예시는 ItemWrapper의 Parse메서드 참고해 주세요

- 형 변환 방식

// enum 변환 방법
itemType = (변환할 Enum)Enum.Parse(typeof(변환할 Enum), 문자열);

// ex
ItemType itemType = (ItemType)Enum.Parse(typeof(ItemType), values[인덱스]);

// 숫자 변환 방법
//숫자 변환: 
int.Parse(values[인덱스];
float.Parse(values[인덱스])

 

- 각 행은 values 배열로 전달됩니다.

 

- 구체적인 예시

[System.Serializable]
public class ItemWrapper : ICsvParsable
{
    [SerializeField] private int itemNum;
    [SerializeField] private ItemType itemType;
    [SerializeField] private string itemName;
    [SerializeField] private string itemToopTip;
    [SerializeField] private float attackSpeed;
    [SerializeField] private float attackDamage;
    [SerializeField] private float durationTime;

    public void Parse(string[] values)
    {
        // [0] item num
        // [1] item type
        // [2] name
        // [3] tooltip
        // [4] attackSpeed
        // [5] attackDamage
        // [6] durationTime
        // [7] PlayerState

        itemNum = int.Parse(values[0]);
        itemType = (ItemType)Enum.Parse(typeof(ItemType), values[1]);
        itemName = values[2];
        itemToopTip = values[3];
        attackSpeed = float.Parse(values[4]);
        attackDamage = float.Parse(values[5]);
        durationTime = float.Parse(values[6]);
    }
}

 

 

2. Resources 폴더에 CSV 파일 추가

  • CSV 파일명은 wrapper 클래스명과 정확히 동일해야 합니다.
  • 예시 csv 파일

ItemWrapper.csv
0.00MB

 

 

3. 변환 실행

  1. 씬의 Converter 오브젝트에서 CsvToJsonConverter 컴포넌트의 className 배열에 클래스명(=CSV 파일명)을 입력합니다.
  2. Inspector에서 [Csv to Json] 버튼을 클릭합니다.
  3. 변환이 완료되면 콘솔에 성공 메시지가 표시됩니다.
  4. JSON 파일은 Application.persistentDataPath 경로에 저장됩니다.
    1. 구제적인 경로
C:\Users\사용자이름\AppData\LocalLow\DefaultCompany\프로젝트이름

 

저장된 Json 불러오기                                                                                     

  • 저장된 클래스를 역직렬화, 리스트로 가져오기
// 저장된 클래스를 역직렬화
List<클래스명> 변수이름 = JsonSerialized.Deserialization<클래스명>("클래스명")

// 사용 예시 
List<ItemWrapper> itemWrapperList = JsonSerialized.Deserialization<ItemWrapper>("ItemWrapper");

 

!!!  주의사항 !!!                                                                                                 

  • CSV 파일, wrapper 클래스, className 배열에 입력한 이름이 모두 일치해야 합니다.
  • CSV 파일은 반드시 Resources 폴더 하위에 위치해야 합니다.
  • CSV 파일이 비어있거나 형식이 잘못된 경우 오류가 발생합니다.

깃허브

https://github.com/kimYouChae/UnityCsvToJsonConverter

 

GitHub - kimYouChae/UnityCsvToJsonConverter

Contribute to kimYouChae/UnityCsvToJsonConverter development by creating an account on GitHub.

github.com

 

내일배움캠프-레벨업세션에서 엑셀 파일을 Json으로 변환하는 기능을 봤는데 
이번 프로젝트에서 그대로 사용하기에는 맞지않다고 느껴서
유니티 내부에서 csv파일을 Json으로 저장하는 기능을 만들어보았다. 

 

📝 CsvToJsonConverter.cs

- 전체코드

public class CsvToJsonConverter : MonoBehaviour
{
    /// <summary>
    /// ***Converter 사용 전 주의사항***
    /// 1. 입력한 string, 클래스명, Recources하위의 csv 데이터 이름이 동일해야합니다.
    /// 2. Recources파일 하위에 csv데이터가 존재해야합니다.
    /// 3. csv 데이터를 파싱해서 사용할 클래스 조건
    ///     (1) 클래스여야합니다.
    ///     (2) ICsvParsable 인터페이스를 구현해야합니다.
    ///     (3) 매개변수가 없는 생성자를 가지고 있어야 합니다.
    ///     : ICsvParsable 인터페이스와 사용예시는 Stage 스크립트를 참고해주세요
    /// </summary>

    [Header("===클래스 이름을 작성해주세요===")]
    public string[] className;

    public void CsvConverByName()
    {
        Debug.Log("CsvConverter메서드입니다");

        for (int i = 0; i < className.Length; i++)
        {
            // 여기서 type은 ? 클래스라고 생각하면 편함 
            // string에 맞는 타입 생성 
            Type type = Type.GetType(className[i]);

            if (type == null)
            {
                Debug.LogError($"해당 클래스({className[i]})를 찾을 수 없습니다.");
                continue;
            }

            if (!typeof(ICsvParsable).IsAssignableFrom(type))
            {
                Debug.LogError($"클래스({className[i]})는 ICsvParsable을 구현해야 합니다.");
                continue;
            }

            // CsvDataParsing<> 클래스의 타입을
            // MakeGeneritType : type으로 제네릭 지정
            // convertype : 즉 CsvDataParsing<클래스명>이 된다
            Type converterType = typeof(CsvDataParsing<>).MakeGenericType(type);

            // CsvDataParsing 인스턴스화 
            // 매개변수는 className[i]
            object converterInstance = Activator.CreateInstance(converterType, className[i]);

            // CsvDataParsing<>의 GetDataArray() 메서드 가져오기 
            MethodInfo method = converterType.GetMethod("GetDataArray");

            if (method != null)
            {
                // GetDataArray 메서드 Invoke
                // return 값은 List<T>이지만 object타입으로 박싱(boxing) 일어남 
                // 원본 데이터 배열 가져오기 (List<T> 타입)
                // 컴파일 타임에는 object, 런타임때는 List<T>
                object dataArray = method.Invoke(converterInstance, null);

                // 원본 타입을 유지한 채 JSON으로 변환
                string json = JsonSerialized.ConvertOriginalListToJson(dataArray, type);

                // 결과 저장
                jsonResults[className[i]] = json;

                // 파일로 저장
                JsonSerialized.SaveJsonToFile(json, className[i]);

                Debug.Log($"{className[i]} 데이터를 성공적으로 변환했습니다.");
            }

        }
    }
}

 

 

- 상세코드

Type type = Type.GetType(className[i]);

클래스 이름을 통해서 클래스 타입을 type변수에 저장한다.

Type converterType = typeof(CsvDataParsing<>).MakeGenericType(type);

CsvDataParsing 클래스의 제네릭 타입을 위에서 지정해준 type(현재 클래스의 타입)으로 설정한다. 

object converterInstance = Activator.CreateInstance(converterType, className[i]);

Reflection의 Activator.CreateInstance를 사용해서 제네릭 클래스인 CsvDataParsing를 인스턴스화 한다.

생성자의 매개변수는 현재 클래스이름 

MethodInfo method = converterType.GetMethod("GetDataArray");

  CsvDataParsing 클래스의 GetDataArray()함수를 MethodInfo에 저장한다 

 

if (method != null)
{
    object dataArray = method.Invoke(converterInstance, null);

  GetDataArray메서드를 실행 

  리턴값은 컴파일 타임에는 object 타입으로 저장되고, 런타임때는 List<T> 타입으로 저장된다

 

    // 원본 타입을 유지한 채 JSON으로 변환
    string json = JsonSerialized.ConvertOriginalListToJson(dataArray, type);

    // 파일로 저장
    JsonSerialized.SaveJsonToFile(json, className[i]);

    Debug.Log($"{className[i]} 데이터를 성공적으로 변환했습니다.");
}

■ JsonSerialized 클래스의 ConvertOriginalListToJson() 메서드를 실행 후 json 문자열을 return받는다

JsonSerialized 클래스의 SaveJsonToFile() 메서드를 실행 후 json 파일을 저장한다. 

 

📝 JsonSerialized.cs

- 전체코드

[SerializeField]
public class ListWrapper<T>
{
    public List<T> values;
}
public static class JsonSerialized
{
    // C:\Users\[user name]\AppData\LocalLow\[company name]\[product name]
    static string savePath = Application.persistentDataPath;

    // 원본 타입의 리스트를 변환하는 메서드 (리플렉션 사용)
    public static string ConvertOriginalListToJson(object dataArray, Type elementType)
    {
        // dataArray는 현재 List<T>
        // 1. 적절한 ListWrapper<tyoe> 타입 생성
        Type wrapperType = typeof(ListWrapper<>).MakeGenericType(elementType);

        // 2. 래퍼 인스턴스 생성
        object wrapper = Activator.CreateInstance(wrapperType);

        // 3. values 필드 가져오기
        FieldInfo valuesField = wrapperType.GetField("values");

        // 4. dataArray를 values 필드에 할당
        // dataArray는 object타입이지만 실제로는 List<T> (매개변수로 List<T>를 넘겼기 때문)
        valuesField.SetValue(wrapper, dataArray);

        // 5. JsonUtility로 직렬화
        return JsonUtility.ToJson(wrapper);
    }

    public static void SaveJsonToFile(string json, string saveFileName)
    {
        try
        {
            string path = Path.Combine(savePath, saveFileName);
            File.WriteAllText(path, json);
            Debug.Log($"{saveFileName}이 저장되었습니다. 경로: {path}");
        }
        catch (Exception ex)
        {
            Debug.LogError($"파일 저장 중 오류 발생: {ex.Message}");
        }
    }
}

 

 

- 상세코드

🔖 ConvertOriginalListToJson() 메서드

    // dataArray는 현재 List<T>
    // 1. 적절한 ListWrapper<tyoe> 타입 생성
    Type wrapperType = typeof(ListWrapper<>).MakeGenericType(elementType);

ListWrapper클래스의 제네릭 타입을 위에서 매개변수의 type(현재 클래스의 타입)으로 설정한다. 

 

    // 2. 래퍼 인스턴스 생성
    object wrapper = Activator.CreateInstance(wrapperType);

 Reflection의 Activator.CreateInstance를 사용해서 제네릭 클래스인 ListWrapper를 인스턴스화 한다.

 

    // 3. values 필드 가져오기
    FieldInfo valuesField = wrapperType.GetField("values");

ListWrapper 클래스의 List<T> 타입의 values변수를 FieldInfo 에 저장한다 

 

    // 4. dataArray를 values 필드에 할당
    // dataArray는 object타입이지만 실제로는 List<T> (매개변수로 List<T>를 넘겼기 때문)
    valuesField.SetValue(wrapper, dataArray);

FieldInfo의 SetValue를 통해서 dataArray를 List<T>에 할당한다

 

    // 5. JsonUtility로 직렬화
    return JsonUtility.ToJson(wrapper);

Json으로 직렬화 후 string을 return 한다 

 

🔖 SaveJsonToFile() 메서드

    string path = Path.Combine(savePath, saveFileName);
    File.WriteAllText(path, json);

json 문자열을 지정한 경로에 , 매개변수로 넘어온 파일이름으로 저장한다 

 

📝 ICsvParsable 인터페이스

public interface ICsvParsable
{
    void Parse(string[] values);
}

 

📝 Stage.cs - 테스트용 클래스 

[System.Serializable]
public class Stage : ICsvParsable
{
    [SerializeField] private int hp;
    [SerializeField] private string name;
    [SerializeField] private List<string> animal;

    public void Parse(string[] values)
    {
        hp = int.Parse(values[0]);
        name = values[1];

        animal = new List<string>();
        string[] temp = values[3].Split('-');
        for (int i = 0; i < temp.Length; i++)
        {
            animal.Add(temp[i]);
        }
    }
}

  [System.Serializable]

             □ 직렬화 하기 위해서 클래스 위에 추가한다

csv를 파싱한 데이터를 필드에 넣기위해서 ICsvParsable 인터페이스를 구현한다

Parse(string[] values)

              필드에 맞게 변수를 형변환해서 필드를 설정한다 

 

📝 CsvJsonButton.cs

[CustomEditor(typeof(CsvToJsonConverter))]
public class CsvJsonButton : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        CsvToJsonConverter mana = (CsvToJsonConverter)target;

        if (GUILayout.Button("Cvs to Json"))
        {
            mana.CsvConverByName();
        }
    }
}

에디터에서 실행하기 위해서 커스텀에디터를 만들어준다

 


사전 준비

🔖 csv에서 파싱할 클래스를 작성한다

🔖 해당 클래스는 반드시 CsvParsable인터페이스를 구현해야한다

🔖 csv 파일 이름 , 클래스 이름, 인스펙터 창에 입력한 클래스 이름이 동일해야한다

🔖 Stage클래스 참고 ! 

 

사용방법 ( 테스트환경 )

1. Resources 폴더 내부에 csv 파일 생성

Stage.csv
0.00MB

 

2. Converter 오브젝트의 리스트에 "Stage"입력 후 "Cvs to Json"버튼 클릭 

3. C:\Users\사용자이름\AppData\LocalLow\DefaultCompany\프로젝트이름

의 경로에 Json파일이 생성되었는지 확인한다 

 


📝 깃허브

https://github.com/kimYouChae/UnityCsvToJsonConverter

 

GitHub - kimYouChae/UnityCsvToJsonConverter

Contribute to kimYouChae/UnityCsvToJsonConverter development by creating an account on GitHub.

github.com

 

목차
1. 저장 시스템
    □ 설계 
2. 저장
    □ NuGet 
    □ Newtonsoft.Json
    □ Json
    □ 직렬화 / 역직렬화
    □ visual Studio에서 사용방법
3. 실제 사용 예시

 

📝 1. 저장 시스템

: nuget의 NewtonJson을 사용하여 클래스를 직렬화 한 뒤 텍스트파일로 저장

: 저장된 텍스트 파일을 불러와서 역직렬화 

 

1. 설계

 

 

 

📝 2. 저장 

1. Nuget

: c# 저장방식을 검색하다 보면  nuget의 NewtonJson을 사용하는 글이 많이 보인다. nuget이 뭘까?

 

https://www.nuget.org/

 

NuGet Gallery | Home

The NuGet Gallery is the central package repository for NuGet, the package manager for .NET.

www.nuget.org

:  " NuGet is the package manager for. NET." 즉 닷넷의 패키지 매니저이다.

 

https://learn.microsoft.com/ko-kr/nuget/quickstart/install-and-use-a-package-in-visual-studio

 

빠른 시작: Visual Studio에서 NuGet 패키지 설치 및 사용(Windows에만 해당)

이 빠른 시작에서는 Windows용 Visual Studio 프로젝트에서 NuGet 패키지를 설치하고 사용하는 방법을 알아봅니다.

learn.microsoft.com

: NuGet 패키지에는 다른 개발자가 프로젝트에서 사용할 수 있도록 만든 재사용 가능한 코드가 포함되어 있다. 

 

2. Newtonsoft.Json

: JSON 관련 작업을 할 때 편리한 기능을 제공하는 JSON 라이브러리 

 

3.Json

📝 what is Json 

     Java Script Object Notation의약자 

    데이터를 저장하고 전송하기 위한 형식

📝Json Data

      이름/값 쌍( 키/값 쌍 )으로 구성된다 

       JSON에서는 키는 큰따옴표로 묶인 문자열이어야 한다

{
  "name": "John",
  "age": 30
}

 

→ 더 자세한 내용은 w3 school 홈페이지 참고!

https://www.w3schools.com/js/js_json_syntax.asp

 

W3Schools.com

W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

www.w3schools.com

 

4. 직렬화 / 역직렬화 

📝Serialization (직렬화)

  문자열/숫자/객체/배열/bool/null 등의 타입을 json 문자열로 변환하는 과정

  JsonConvert.SerializeObject 사용

Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Sizes = new string[] { "Small" };

string json = JsonConvert.SerializeObject(product);

 

📝 Deserializaion (역직렬화)

  json 문자열을 문자열/숫자/객체/배열/bool/null 등의 타입으로 재변환하는 과정, 직렬화의 반대과정 

JsonConvert.DeserializeObject <T> 사용

string json = @"{
  'Name': 'Bad Boys',
  'ReleaseDate': '1995-4-7T00:00:00',
  'Genres': [
    'Action',
    'Comedy'
  ]
}";

Movie m = JsonConvert.DeserializeObject<Movie>(json);

 


5. visual Studio에서 사용방법

□ 솔루션 탐색기 우클릭 → Nuget 패키지 관리 선택

□ newton 검색 후 다운로드

 

📝 3. 실제 사용 

1. 직렬화 & 저장

 // 직렬화 된 string 반환
 private string SerializedObject() 
 {
     try 
     {
         PlayerSaveData data = new PlayerSaveData();
        
        // 직렬화
         string json = JsonConvert.SerializeObject(data);

         //Console.WriteLine(json);
         return json;
     }
     catch (Exception e) 
     {
         Console.WriteLine($"직렬화 중 오류 발생 : {e.Message}");
         return string.Empty;
     }
   
 }
public void SaveData() 
{
    Console.WriteLine("데이터를 저장합니다.");

    // 직렬화
    string jsonString = SerializedObject();

    // 해당 디렉토리 (폴더) 가 없으면 생성
    if (!Directory.Exists(savePath))
        Directory.CreateDirectory(savePath);

    // string을 textFile로 저장
    // 파일이 이미 있으면 덮어씀
    using (StreamWriter sw = File.CreateText(savePath + saveFileName))
    {
        sw.WriteLine(jsonString);
    }
}

 

2. 역직렬화 / 불러오기 

 public void LoadData() 
 {
     // 경로 + 파일명에 파일이 있으면 ?
     if (File.Exists(savePath + saveFileName))
     {
         Console.WriteLine(" 저장파일이 있습니다.");

         // 불러오기 
         string desString = File.ReadAllText(savePath + saveFileName);

         // 역 직렬화
         try
         {
             PlayerSaveData data = JsonConvert.DeserializeObject<PlayerSaveData>(desString);
         }

         catch (Exception e) { Console.WriteLine(e); }
     }
     else 
     {
         Console.WriteLine(" 저장파일이 없습니다.");
     }
 }

 


📝디렉토리/텍스트파일을 저장하고 불러오는 방법

https://youcheachae.tistory.com/33

 

[c#][TextRPG] 3. c#의 System.IO를 이용한 파일 시스템 작업

목차1.Stream / StreamWriter2. 디렉터리 존재 여부3. 디렉토리 생성 / 삭제4. 파일 존재 여부5. 파일 생성 / 삭제 6. 파일 읽기  📝 System.IO 네임스페이스using System.IO;: 파일 시스템 작업 ( 디렉터리 / 파

youcheachae.tistory.com


📝 깃허브

https://github.com/kimYouChae/SpartaCodingClub

 

GitHub - kimYouChae/SpartaCodingClub

Contribute to kimYouChae/SpartaCodingClub development by creating an account on GitHub.

github.com

 

+ Recent posts