반응형

Json이란?

JavaScript Object Notation의 약자로 경량 데이타 교환 형식입니다.
Unity에서 JsonUtility라는 클래스로 기능을 쉽게 사용 할 수 있으며 이 포스팅은 Unity에서 Json 파일 입출력 기본 사용법과 몇가지 이슈에 대해 다룹니다.

 


예제 준비

[Serializable]
public class CharacterData
{
    public string sTypeName = string.Empty;
    public string sName = string.Empty;
    public int nLevel = -1;
    public List<string> sItemList = new List<string>();

    public virtual void Log()
    {
        Debug.Log(sTypeName);
        Debug.Log(sName);
        Debug.Log(nLevel);
        foreach(string sItems in sItemList)
        {
            Debug.Log(sItems);
        }
    }
}

[Serializable]
public class CharacterData_Warrior : CharacterData
{
    public float fRage = 0.0f;

    public CharacterData_Warrior()
    {
        sTypeName = typeof(CharacterData_Warrior).ToString();
    }

    public override void Log()
    {
        base.Log();
        Debug.Log(fRage);
    }
}

[Serializable]
public class CharacterData_Archer : CharacterData
{
    public int nArrow = 0;

    public CharacterData_Archer()
    {
        sTypeName = typeof(CharacterData_Archer).ToString();
    }

    public override void Log()
    {
        base.Log();
        Debug.Log(nArrow);
    }
}

[Serializable]
public class CharacterData_Mage : CharacterData
{
    public float fMp = 0.0f;

    public CharacterData_Mage()
    {
        sTypeName = typeof(CharacterData_Mage).ToString();
    }

    public override void Log()
    {
        base.Log();
        Debug.Log(fMp);
    }
}

Json를 잘 활용하기 위해 예제 클래스 데이터를 준비합니다.

위 예시 코드는 CharacterData라는 부모 클래스가 있고 아래 3가지 자식 클래스를 준비했습니다.

위 예시를 활용하여 Json을 저장하고 읽을때 클래스 타입에 맞게 읽는 것까지 하기 위해 설계했습니다.

 

 

직렬화

해당 클래스의 정보가 Json데이터로 똑바로 변환되기 위해서는 직렬화 Attribute를 설정해야 합니다.

 

 


Json 파일 입출력

1. 저장하기 

 //! Json파일 저장 함수
    void SaveJsonData(CharacterData pData)
    {
        //! Json변환
        string sJsonData = JsonUtility.ToJson(pData);

        //! 파일 저장
        string sPath = string.Format("Assets/JsonTest/Datas/{0}/{1}.json", pData.sTypeName, pData.sName);
        System.IO.FileInfo file = new System.IO.FileInfo(sPath);
        file.Directory.Create();
        File.WriteAllText(file.FullName, sJsonData);
    }

코드를 위와 같이 간단합니다.

저장하는 경로에 중간 경로가 누락되더라도 자동으로 폴더를 만들어서 json파일을 생성합니다.

 

void SaveData()
    {
        {
            CharacterData_Warrior pCharacterData = new CharacterData_Warrior();
            pCharacterData.sName = "RatKiller";
            pCharacterData.nLevel = 5;
            pCharacterData.sItemList.Add("Sword");
            pCharacterData.sItemList.Add("Hammer");
            pCharacterData.sItemList.Add("HandAxe");
            pCharacterData.fRage = 105.0f;

            SaveJsonData(pCharacterData);
        }

        {
            CharacterData_Archer pCharacterData = new CharacterData_Archer();
            pCharacterData.sName = "ArrowMaster";
            pCharacterData.nLevel = 12;
            pCharacterData.sItemList.Add("Bailter");
            pCharacterData.sItemList.Add("bow");
            pCharacterData.sItemList.Add("K-2");
            pCharacterData.nArrow = 100000;

            SaveJsonData(pCharacterData);
        }

        {
            CharacterData_Mage pCharacterData = new CharacterData_Mage();
            pCharacterData.sName = "ThunCol";
            pCharacterData.nLevel = 115;
            pCharacterData.sItemList.Add("Stick");
            pCharacterData.fMp = 20.0f;

            SaveJsonData(pCharacterData);
        }
    }

위 코드를 클래스를 각 타입별로 생성해서 Json저장함수를 호출하는 코드입니다. 실제 사용 예시죠

 

성공적으로 파일 생성이 완료됬고, 내용물도 잘들어가 있습니다.

 

 

2. 불러오기

 //! Json파일 읽기 - 경로기반
    void LoadJsonData_FromPath(string sPath)
    {
        System.IO.FileInfo loadfile = new System.IO.FileInfo(sPath);
        if (loadfile.Exists == false)
        {
            Debug.LogError("파일 없음");
            return;
        }
        string sJsonData = File.ReadAllText(loadfile.FullName);
        Load_Character(sJsonData);
    }

    //! Json파일 읽기 - 에셋 기반
    void LoadJsonData_FromAsset(TextAsset pAsset)
    {
        if (pAsset==null)
        {
            Debug.LogError("파일 없음");
            return;
        }
        Load_Character(pAsset.text);
    }

    void Load_Character(string sJsonData)
    {
        //! Json데이타 -> 클래스 구조체로 데이터 변환
        CharacterData pData = JsonUtility.FromJson<CharacterData>(sJsonData);

        //! Type구분해서 다시 한번 형식에 알맞게 데이터 변환
        string sTypeName = pData.sTypeName;
        if (sTypeName == typeof(CharacterData_Warrior).ToString())
        {
            CharacterData_Warrior pData_Detail = JsonUtility.FromJson<CharacterData_Warrior>(sJsonData);
            pData_Detail.Log();
        }
        else if (sTypeName == typeof(CharacterData_Archer).ToString())
        {
            CharacterData_Archer pData_Detail = JsonUtility.FromJson<CharacterData_Archer>(sJsonData);
            pData_Detail.Log();
        }
        else if (sTypeName == typeof(CharacterData_Mage).ToString())
        {
            CharacterData_Mage pData_Detail = JsonUtility.FromJson<CharacterData_Mage>(sJsonData);
            pData_Detail.Log();
        }
    }

불러오는 함수는 경로기반과 에셋 기반 두 가지를 구현했습니다.

 

실제 사용 예시이고 에셋은 TextAsset클래스를 public등으로 선언해서 Json데이터를 가져오는 방식을 뜻합니다.

 

그리고 간단한 응용예시로 Load_Character함수에서 먼저 부모클래스 형식으로 Json을 읽어서 타입검사를해서 해당 타입에 맞게 다시 변환하는 예시를 작성했습니다.

 

결과 : 각 타입에 맞게 json데이터를 읽어 출력까지 잘됩니다.

 

 

반응형

WRITTEN BY
CatDarkGame
Technical Artist dhwlgn12@gmail.com

,