본문 바로가기
Utils

Unity, Json 리스트 파일 저장하기

by Client. DJ 2024. 7. 20.
반응형

JsonUtilityExtention.unitypackage
0.00MB

리스트 저장

JsonUtility를 통해 ToJson()하면 List 형식의 저장이 되지 않습니다. 하지만 하나의 클래스로 감싸서 저장하면 사용할 수 있습니다.

스크립트

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;

public static class JsonUtilityExtention
{
    [Serializable]
    private class JsonWrapper<T>
    {
        public List<T> datas;
    }

    /// <summary>
    /// 단일 저장
    /// </summary>
    /// <typeparam name="T">클래스 타입</typeparam>
    /// <param name="data">데이터</param>
    /// <param name="path">경로</param>
    public static void FileSave<T>(T data, string path)
    {
        JsonWrapper<T> wrapper = new JsonWrapper<T>();
        wrapper.datas = new List<T> { data };
        string json = JsonUtility.ToJson(wrapper);
        json = PrettyPrintJson(json);
        if (!path.StartsWith('/')) path = "/" + path;
        File.WriteAllText(Application.dataPath + path, json);
        AssetDatabase.Refresh();
    }

    /// <summary>
    /// 단일 불러오기
    /// </summary>
    /// <typeparam name="T">클래스 타입</typeparam>
    /// <param name="path">경로</param>
    /// <returns>데이터 반환</returns>
    public static T FileLoad<T>(string path)
    {
        if (!path.StartsWith('/')) path = "/" + path;
        string json = File.ReadAllText(Application.dataPath + path);
        JsonWrapper<T> wrapper = JsonUtility.FromJson<JsonWrapper<T>>(json);
        return wrapper.datas[0];
    }

    /// <summary>
    /// 리스트 타입 저장
    /// </summary>
    /// <typeparam name="T">클래스 타입</typeparam>
    /// <param name="datas">데이터 리스트</param>
    /// <param name="path">경로</param>
    public static void FileSaveList<T>(List<T> datas, string path)
    {
        JsonWrapper<T> wrapper = new JsonWrapper<T>();
        wrapper.datas = datas;
        string json = JsonUtility.ToJson(wrapper);
        json = PrettyPrintJson(json);
        if (!path.StartsWith('/')) path = "/" + path;
        File.WriteAllText(Application.dataPath + path, json);
        AssetDatabase.Refresh();
    }

    /// <summary>
    /// 리스트 타입 불러오기
    /// </summary>
    /// <typeparam name="T">클래스 타입</typeparam>
    /// <param name="path">경로</param>
    /// <returns>데이터 리스트 반환</returns>
    public static List<T> FileLoadList<T>(string path)
    {
        if (!path.StartsWith('/')) path = "/" + path;
        string json = File.ReadAllText(Application.dataPath + path);
        JsonWrapper<T> wrapper = JsonUtility.FromJson<JsonWrapper<T>>(json);
        return wrapper.datas;
    }

    /// <summary>
    /// Json 줄정리
    /// </summary>
    /// <param name="json">json 형식의 텍스트</param>
    /// <returns>정리된 json 텍스트</returns>
    private static string PrettyPrintJson(string json)
    {
        const int indentSpaces = 4;
        int indent = 0;
        bool quoted = false;
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < json.Length; i++)
        {
            char ch = json[i];

            switch (ch)
            {
                case '{':
                case '[':
                    sb.Append(ch);
                    if (!quoted)
                    {
                        sb.AppendLine();
                        sb.Append(new string(' ', ++indent * indentSpaces));
                    }
                    break;
                case '}':
                case ']':
                    if (!quoted)
                    {
                        sb.AppendLine();
                        sb.Append(new string(' ', --indent * indentSpaces));
                    }
                    sb.Append(ch);
                    break;
                case '"':
                    sb.Append(ch);
                    bool escaped = false;
                    int index = i;
                    while (index > 0 && json[--index] == '\\')
                    {
                        escaped = !escaped;
                    }
                    if (!escaped)
                    {
                        quoted = !quoted;
                    }
                    break;
                case ',':
                    sb.Append(ch);
                    if (!quoted)
                    {
                        sb.AppendLine();
                        sb.Append(new string(' ', indent * indentSpaces));
                    }
                    break;
                case ':':
                    sb.Append(ch);
                    if (!quoted)
                    {
                        sb.Append(" ");
                    }
                    break;
                default:
                    if (quoted || !char.IsWhiteSpace(ch))
                    {
                        sb.Append(ch);
                    }
                    break;
            }
        }

        return sb.ToString();
    }
}

예제

메뉴로 호출하여 테스트

using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestJsonUtilityExtention : MonoBehaviour
{
    [Serializable]
    private class TestData
    {
        public string name;
        public float value;

        public override string ToString() => $"name: {name}, value: {value}";
    }

    public static string JSON_PATH = "/JsonUtilityExtention/Test.json";
    public static string LIST_JSON_PATH = "/JsonUtilityExtention/ListTest.json";

    [MenuItem("JsonUtilityExtention/Test Save List")]
    private static void TestSaveList()
    {
        List<TestData> datas = new List<TestData>
        {
            new TestData
            {
                name = "test1",
                value = 1.1f,
            },
            new TestData
            {
                name = "test2",
                value = 3.2f,
            },
            new TestData
            {
                name = "test3",
                value = 5.6f,
            },
            new TestData
            {
                name = "test4",
                value = 2.3f,
            }
        };

        JsonUtilityExtention.FileSaveList(datas, LIST_JSON_PATH);
    }

    [MenuItem("JsonUtilityExtention/Test Load List")]
    private static void TestLoadList()
    {
        List<TestData> datas = JsonUtilityExtention.FileLoadList<TestData>(LIST_JSON_PATH);
        string s = "Data List: \n";
        foreach (var data in datas)
        {
            s += data + "\n";
        }
        Debug.Log(s);
    }

    [MenuItem("JsonUtilityExtention/Test Save")]
    private static void TestSave()
    {
        var data = new TestData
        {
            name = "test1",
            value = 1.1f,
        };

        JsonUtilityExtention.FileSave(data, JSON_PATH);
    }

    [MenuItem("JsonUtilityExtention/Test Load")]
    private static void TestLoad()
    {
        var data = JsonUtilityExtention.FileLoad<TestData>(JSON_PATH);
        Debug.Log("Data: " + data);
    }
}

마무리

파일 저장에 이슈가 있어서 알아보고 작성해봤습니다. 유용하게 사용하길 바랍니다. 😁

반응형

댓글