티스토리 뷰

유니티

유니티 - JSON 활용 n차원 배열

쉬엄쉬엄하자 2020. 8. 26. 16:28
728x90

 

유니티에서는 JsonUtility를 활용해 시리얼라이즈와 디시리얼라이즈 하는 기능을 제공하고 있습니다.

1차원의 자료형까지는 모두 코드몇줄만 가지고 시리얼라이즈하여 서버와 클라이언트가 통신할 수 있죠.

예를들어 리스트, 벡터, 1차원배열 같은 자료형은 모두 Json으로 만들 수 있습니다.

 

하지만 서버와 통신하는 게임을 개발하다보면 서버와 클라이언트간의 2차원배열 이상의 데이터를 주고받아야 하는 경우가 있습니다.

 

예를들어 게임 필드의 지형 정보를 2차원 배열로 표현하여 플레이어간의 주고받을 수 있도록 통신하는 기능을 구현하고 싶다면 클라이언트에서 2차원배열을 보내고 서버가 브로드캐스트하여 다른클라이언트가 2차원배열 정보를 받을 수 있어야하죠.

 

하지만 이차원 배열은 JsonUtility의 ToJson()으로 시리얼라이즈 할 수 없습니다.

 

바로 예제 코드를 보시면

우선 Json 데이터 파싱을 위한 클래스를 준비합니다.

 

DataToJsonData메소드는 특정 클래스의 인스턴스를 매개변수로 받아 이를 Json으로 바꿔주는 ToJson을 호출하고 이 결과를 출력합니다.

using UnityEngine;
using System.Text;

public class DataParser : MonoBehaviour
{
    public static T ReadJsonData<T>(byte[] buf)
    {
        var strByte = Encoding.Default.GetString(buf);
        Debug.Log("strByte : " + strByte);
        //byte 배열을 string으로 변환
        return JsonUtility.FromJson<T>(strByte);
    }

    public static byte[] DataToJsonData<T>(T obj)
    {
        var jsonData = JsonUtility.ToJson(obj);
        Debug.Log("json : " + jsonData.ToString());
        //string을 byte 배열로 변환
        return Encoding.UTF8.GetBytes(jsonData);
    }
}

 

그리고 다음은 이차원배열을 담고 있는 잘못된 클래스를 만듭니다.

    public class WrongClass
    {
        public int[,] twoDimen;
        public int test;
        public WrongClass(int[,] _twoDimen, int _test)
        {
            twoDimen = _twoDimen;
            test = _test;
        }
    }

int형 이차원 배열을 가지고 있고 또다른 int 형 변수를 필드로 가지고 있는 클래스입니다.

이 클래스의 정보를 Json에 담아 통신하고 싶기때문에 이 클래스의 인스턴스를 Json화 시켜보겠습니다.

 

        int[,] twoDimenInt = new int[,] { { 0, 0, 0 }, { 1, 1, 1 } };
        WrongClass wrongClass = new WrongClass(twoDimenInt, 1);
        DataParser.DataToJsonData<WrongClass>(wrongClass);

분명 twoDimen의 값까지 포함된 json이 리턴되야 하지만 int형 변수 test만 값만 json에 포함되었습니다.

그러면 이차원 배열을 json화 시키는 방법을 알아보겠습니다.

 

생각보다 쉽게 조금만 더 이를 응용하면 되는데요.

일차원의 자료형은 json화 시키는게 가능하기 때문에 일차원의 자료형을 감싸는 클래스의 배열을 json화 시키면 됩니다.

 

즉 필드로 일차원 배열을 갖는 클래스를 생성하고 최종 json화할 클래스에는 일차원 배열을 갖는 클래스의 배열을 필드로 가지는것이죠.

 

예를들어 다음과 같은 클래스를 만듭니다.

    [System.Serializable]
    public class IntArr
    {
        public int[] intArr;
        public IntArr(int[] _intArr)
        {
            intArr = _intArr;
        }
    }

 

여기서 System.Serializable을 명시해줘야 해당 클래스를  json화 시킬 수 있습니다.

이 클래스는 일차원 int형 배열을 필드를 가지고 있는 클래스입니다.

 

그리고 통신을 위한 목적 클래스를 만듭니다.

 

    public class Message
    {
        public IntArr[] twoDimen;
        public int test;

        public Message(IntArr[] _twoDimen, int _test)
        {
            twoDimen = _twoDimen;
            test = _test;
        }
    }

위에서 선언한 IntArr클래스의 일차원 배열을 필드로 가지고 있는 통신 메세지 클래스입니다.

 

이제 이 클래스의 인스턴스를 만들어 json화 시켜보겠습니다.

 

        IntArr[] twoDimenArr = new IntArr[] { new IntArr(new int[] { 0, 0, 0 }), new IntArr(new int[] { 1, 1, 1 }) };
        Message message = new Message(twoDimenArr, 1);
        DataParser.DataToJsonData<Message>(message);

 

먼저 IntArr의 배열 변수를 만들고 이를 Message클래스의 생성자에 넣었습니다.

그 결과로

 

원하는대로 2차원배열의 정보가 있는 json이 생성되었습니다.

하지만 위처럼 IntArr의 배열을 사용하려고 할 경우 인스턴스를 생성하는데 너무 복잡한 코드가 됩니다.

배열은 선언과 동시에 크기를 결정해야하는 자료형이기 때문이죠.

 

배열을 사용하는것이 불편하고 유동적으로 2차원배열을 만들고 싶다면 List를 사용합니다.

 

        List<IntArr> twoDimenArr = new List<IntArr>();
        twoDimenArr.Add(new IntArr(new int[] { 0, 0, 0 }));
        twoDimenArr.Add(new IntArr(new int[] { 1, 1, 1 }));

        Message message = new Message(twoDimenArr, 1);
        DataParser.DataToJsonData<Message>(message);

위와 동일한 결과를 주지만 이차원 배열에 유동적으로 데이터를 추가할 수 있습니다.

 

이를 활용하여 n차원의 자료형을 다룰 수 있지만 2차원보다 높은 차원의 자료형일 경우 파싱하거나 데이터를 입력하는거 자체가 매우 번거로울 수 있습니다.

 

다음에는 문자열을 활용하여 n차원의 자료형을 json으로 변환하는 방법을 다뤄보겠습니다.

댓글