[Unity] Csv To Json 변환 툴
내일배움캠프-레벨업세션에서 엑셀 파일을 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 파일 생성
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