공부일지

[Unity]Json을 이용한 직렬화 - 작성중 본문

UnityProjects/Item

[Unity]Json을 이용한 직렬화 - 작성중

이하택 2023. 10. 31. 12:56

목차


먼저 프로젝트 기한이 두 달 남은 상태에서 공부용으로 조사한거라 코드를 거의 들고와 죄송죄송;;;

프로젝트 구현하면서 천천히 변경하겠음. 히히;;;

Step0-1. 직렬화, 역직렬화

  • 종이로 출력된 종이 뭉치를 서버로 보내고 싶어도 데이터가 아닌 실물(객체)이기 때문에 보낼 수 없음
    • 최소한 스캔 떠서 이미지로 변환시켜야 하지
    • 수정 가능한 파일로 보내고 싶으면 엑셀 파일을 찾던가 서류를 보고 직접 찍어내던가
  • 객체에 대한 정보를 서버 등에 저장하거나 전송하기에 적합하도록 변환하는게 직렬화.
  • 그걸 다시 객체로 푸는게 역직렬화

System.Text.Json 네임스페이스는 JSON(JavaScript Object Notation)에서 직렬화 및 역직렬화하는 기능을 제공

Serialization : 개체의 상태(:속성 값)를 저장매체에 저장하거나 바이너리 형태로 네트워크를 통해 전달할 수 있는 형식으로 변환하는 프로세스

Deserializtion : 직렬화된 형식에서 개체를 다시 생성.

Stream이란

일련의 데이터가 한 곳에서 다른 곳으로 직렬로 이동하는 상태(흐름)

: 걍 프로그램과 주변 장치가 통신하는 수단이라는 뜻

직렬화의 장단점

장점

  • DOM을 이용하지 않고 XML 수정
  • 다른 어플리케이션으로부터 객체를 전달할 수 있다.
  • 다른 도메인으로 객체를 전달할 수 있다.
  • 방화벽에 제약을 받지 않고 객체를 XML 문자열 형태로 전달 할 수 있다.

단점

  • 직렬화, 역직렬화는 자원의 소모가 많다?
  • 네트워크를 통해 전달할 경우 지연 문제가 발생할 수 있다.
  • 안전하지 않고(제 3자가 수정 가능하므로), 많은 저장 공간을 차지하며, public 클래스에 대해서만 직렬화가 이뤄질 수 있으므로 private이나 internal 클래스는 직렬화 할 수 없다.


Step1. Json이란

  • 웹, 네트워크 기준, 서버와 클라이언트 사이 데이터 송수신용 개방형 표준 포맷.
  • 어떻게 서버와 클라이언트 사이 데이터를 주고 받는지
  • Json 포맷은 텍스트로 되어있어 사람이 이해하기 쉽다.

  • 데이터 타입 : 정수, 실수, 문자열, 불리언, null 등

  • 중괄호 : 객체, 대괄호 : 배열

  • 언제 씀?
    • 저장, 통신 등
  • 어캐 씀?
    • 유니티 지원 기능

  • 단, 미스나면 바로 깨져서 검사기 한번 거치고 사용하자.
class Data
{
	public string name,
	public int level,
	public int coin = 100,
	public bool skill
}

public class Test : MonoBehaviour
{
	Data player = new Data() { name = "chad", level = 50, coin = 200, skill = false }
	void Start()
	{
		string jsonData = JsonUtility.ToJson(player);

		Data player2 = JsonUtility.FromJson<Data>(jsonData);
		print(player2.name);
		print(player2.level);
		print(player2.coin);
		print(player2.skill);
	}
}


Step2. Json 파싱

파싱(Parsing) : 구문분석, 문장을 이루는 구성 성분을 분해하고 위계 관계를 분석해 구조를 결정하는 것. 즉 데이터를 조합해 원하는 데이터를 빼내는 것

단일 객체 불러오기

Serializable 클래스 생성

json 객체를 불러오려면 객체를 래핑할 클래스를 만들어야 한다.

가령 객체에서 hp, atk, def 등에 대한 정보를 꺼내오려면 아래와 같은 클래스나 객체가 필요함.

[System.Serializable]
class Stat
{
	public int hp, atk, def;
}

Json 파일 읽기

var loadedJson = Resources.Load<TextAsset>("Json/Stats");
stat my Stat = JsonUtility.FromJson<Stats>(loadedJson.ToString());

다중 객체 불러오기[여기부터 보완]

{
	"EquipableItems": [
		{
			"part":"Head",
			"damage":"0",
			"defance":"10",
		}	
		{
			"part":"Glove",
			"damage":"0",
			"defance":"7",
		}
	]
}

위 경우 JsonUtility는 한 클래스로 가져오지 못함.

따라서 json 파일에서 객체로 보이는 건 전부 다 클래스로 감싸줘야함.

[System.Serializable]
class EquipInfo : IComparable
{
	public string part;
	public int hp, atk, def;
}

[System.Serlizable]
class EquipData
{
	public EquipInfo[] EquipableItems;
}
[System.Serlizable]
class EquipData
{
	public List<EquipInfo> EquipableItems;
}
  • 배열을 담으려면 EquipInfo의 배열로 이뤄진 새로운 클래스나 배열을 정의

단, Json의 프로퍼티 이름과 배열/리스트의 이름이 같아야 함을 주의하도록.

여기까지 파싱


void Start()
{
	TextAsset textAsset = Resources.Load<TextAsset>("~/EquipableItems");
	EquipData EquipableItems = JsonUtility.FromJson<EquipableItems>(textAsset.text);
}

다시 Json으로 변환하려면

string classToJson = JsonUtility.ToJson(lottoList);

다중 객체 내부의 배열 프로퍼티
{
	"skills": [
		{
			"type": "attack",
			"method": 
			[
				{
					"name": "rangedAttack",
					"attackDmg": 45,
					"heal" : 0
					"target": [ 1 ]
				},
				{
					"name": "distanceAttack",
					"attackDmg": 25,
					"heal" : 0
					"target": [ 1, 2, 3 ]
				}
			]
			"type": "heal",
			"method": 
			[
				{
					"name": "singleheal",
					"attackDmg": 0,
					"heal" : 50
					"target": [ 1 ]
				},
				{
					"name": "multiheal",
					"attackDmg": 0,
					"heal" : 25
					"target": [ 1, 2, 3 ]
				}
			]
		]
	}
}
//대충 작성 나중에 고치자
//아마 구조적으로 잘못 쓴 것 같은데 급해서 쩔수 없음.

  1. 새로운 클래스 정의
[Serializable]
public class SkillCase //aray of objects
{
	public string name;
	public int damage;
	public int heal;
	public int[] target;
}

  1. 파싱
public class ParsingJson : MonoBehaviour
{
	[Serializable]
	public class PlayerSkill
	{
			public SkillCase[] playerskill;
	}

	[Serializable]
	public class SkillNumbers
	{
		public PlayerSkill[] skills;
	}

	void Start()
	{
		TextAsset textAsset = Resources.Load<TextAsset>("~/skills");
		SkillNumbers skillList = JsonUtility.FromJson<SkillNumbers>(textAsset.text);
		foreach ( PlayerSkill skill in skillList.skills )
		{
			//대충 출력 함수 코드
		}
		
		//비직렬화 후 디버그
		string classToJson = JsonUtility.ToJson(skillList);
		Debug.Log(classToJson);
	}
}

Json 출력

  1. Json 쓰기
string fileName = "test.json";
string path = Application.dataPath + "/" + fileName;

File.WriteAllText(path, classToJson);

  1. prettyPrint 옵션 == json 파일 정렬 저장(?) 기능
string classToJson = JsonUtility.ToJson(lottoList, true /* prettyPrint */);

Json 파일 읽기

나중에 채워 넣기

Json 파일 쓰기

JObject configData = new Object
{
	new JProperty("IP", "");
	new JProperty("IP", "");
	new JProperty("IP", "");
	new JProperty("IP", "");
	new JProperty("IP", "");
{
configData.Add("USERS", JArray.FromObject(userList));
FIle.WriteAllText(Path, configData.ToString());

궁금한점

  • 클래스 상속 받는 것 처럼
    • item - equip
    • item- stackable
    • 등으로 작성하고 정규화를 이용해 탐색하고 싶은데
  • 어캐 작성함?
    • 걍 같은 원소를 가지도록 작성하고 원할 때 파싱하면 될 듯? 아마도?
      • 해보고 안되면 물어봐야징


Step3. JsonUtility와 Json.NET 혹은 Newtonsoft.Json

아래 내용은 아직 변형할 능력도 없고 프로젝트 중이라 시간이 없어서

자료 모으는 느낌으로 다른 블로그에서 긁어온 것.

차후 프로젝트에서 사용한 코드로 대체하겠음

NewtonSoft.Json

나중에 작성

지금은 뉴톤으로 안쓸거라

나중에 필요하면 조사하고 작성할 듯

  • 멤버 함수라도 적으려 했는데 왜 안 보이지?

JsonUtility 예시 11

Json데이터 클래스 생성

[Serializable]
public class JsonData
{
    public string name;
    public int age;
    public float height;
    public bool man;
    public string description;
    public string[] tools;
}

클래스 인스턴스 생성 후 값 할당

JsonData jsonData = new JsonData();
jsonData = new JsonData();
jsonData.name = "coderzero";
jsonData.age = 48;
jsonData.height = 172.5f;
jsonData.man = true;
jsonData.description = null;
jsonData.tools = new string[3];
jsonData.tools[0] = "Unity";
jsonData.tools[1] = "Visual Studio";
jsonData.tools[2] = "Phtoshop";

인스턴스를 Json 포맷으로 직렬화

string toJson = JsonUtility.ToJson(jsonData);
{"name":"coderzero","age":48,"height":172.5,"man":true,"description":"","tools":["Unity","Visual Studio","Phtoshop"]}

Json 포맷에서 클래스나 구조체로 역직렬화

JsonData fromJson = JsonUtility.FromJson<JsonData>(toJson);

파일 저장

File.WriteAllText(@"D:\JsonExample.json", toJson);

파일 읽기

string readJson = File.ReadAllText(@"D:\JsonExample.json");

  • 예제
    using UnityEngine;
    using System; // 2.1 네임스페이스 Serializable
    using System.IO; // 2.1 네임스페이스 File
    
    // 2.2 Json 데이터 클래스 생성
    [Serializable]
    public class JsonData
    {
        public string name;
        public int age;
        public float height;
        public bool man;
        public string description;
        public string[] tools;
    }
    
    public class JsonExample : MonoBehaviour
    {
        void Start()
        {
            // 2.3 클래스 인스턴스 생성 후 값 할당
            JsonData[] jsonData = new JsonData[2];
            jsonData[0] = new JsonData();
            jsonData[0].name = "coderzero";
            jsonData[0].age = 48;
            jsonData[0].height = 172.5f;
            jsonData[0].man = true;
            jsonData[0].description = null;
            jsonData[0].tools = new string[3];
            jsonData[0].tools[0] = "Unity";
            jsonData[0].tools[1] = "Visual Studio";
            jsonData[0].tools[2] = "Phtoshop";
    
            jsonData[1] = new JsonData();
            jsonData[1].name = "coderzero";
            jsonData[1].age = 48;
            jsonData[1].height = 172.5f;
            jsonData[1].man = true;
            jsonData[1].description = null;
            jsonData[1].tools = new string[2];
            jsonData[1].tools[0] = "3D Max";
            jsonData[1].tools[1] = "Photoshop";
    
            // 2.4 인스턴스를 Json 포맷으로 직렬화
            string toJson0 = JsonUtility.ToJson(jsonData[0]);
            Debug.Log(toJson0); // 출력 : {"name":"coderzero","age":48,"height":172.5,"man":true,"description":"","tools":["Unity","Visual Studio","Phtoshop"]}
    
            string toJson1 = JsonUtility.ToJson(jsonData[1]);
            Debug.Log(toJson1); // 출력 : {"name":"coderzero","age":48,"height":172.5,"man":true,"description":"","tools":["3D Max","Photoshop"]}
    
            // 2.5 Json 포맷에서 클래스나 구조체로 역직렬화
            JsonData fromJson = JsonUtility.FromJson<JsonData>(toJson0);
            Debug.Log(fromJson.name); // 출력 : coderzero
    
            // 2.6 파일 저장
            File.WriteAllText(@"D:\JsonExample.json", toJson1);
    
            // 2.7 파일 읽기
            string readJson = File.ReadAllText(@"D:\JsonExample.json");
            Debug.Log(readJson); // 출력 : {"name":"coderzero","age":48,"height":172.5,"man":true,"description":"","tools":["3D Max","Photoshop"]}
        }
    }

JsonUtility 예시 22
대충 Json

암튼 위에 Json 파일임. ㅇㅇ 파싱해야함ㅇㅇ.

using System.IO;

public class ParsingJson : MonoBehaviour
{
	void Start()
	{
		string filePath = "~~/Equipment.Json";
		string json = File.ReadAllText(filePath);
	}
}
TextAsset textAsset = Resources.Load<TextAsset>("Json/Lotto1");
  • TextAsset을 이용해 파일을 불러온다.


using System; /* for Serializable */
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ParsingJson : MonoBehaviour
{
    [Serializable]
    public class Items
    {
        public int id;
        public string name;
				public string part;
        public int atk;
        public int def;
    }
    
    ...
}
  • Json을 Class나 Struct로 만들기
  • JSON 포맷으로 변환하기 위해서는 [Serializable]선언 필요
    • json 프로퍼티대로 class를 정의하고 선언
  • 이때, Json파일에 존재하지 않는 프로퍼티가 존재할 경우 default 값으로 초기화되고 에러를 발생시키지 않는다.

void Start()
{
	TextAsset textAsset = Resources.Load<TextAsset>("~/Equipment");
	Items equipItem = JsonUtility.FromJson<Items>(textAsset.text);
}


File.WriteAllText(filePath, classToJson);
  • 파일 내보내기?

JsonUtility 멤버함수

  • JsonUtility.FromJson : Json string을 받아 새 object를 생성해서 리턴.
    • object의 클래스는 [System.Serializable]을 지원해줘야하고 public이어야 한다.
    • 일반 class와 struct만 지원 (MonoBehaviour, ScriptableObject 지원ㄴㄴ)
  • JsonUtility.FromJsonOverwrite : Json String과 기존 object 받아, 기존 obejct에 Json 데이터 덮어씌워줌.
    • object의 클래스는 [System.Serializable]을 지원해줘야하고 public이어야 한다.
    • 일반 class와 struct만 지원 (MonoBehaviour, ScriptableObject 지원ㅇㅇ)
  • JsonUtility.ToJson : object 받아서, object 정보를 Json string으로 생성해서 리턴

자주 사용하는 함수와 키워드들(추가 조사 필요)

  • File.ReadAllText : 텍스트 파일을 열고, 파일의 모든 텍스트를 문자열로 읽어 들인 뒤 닫는다.
    • File.ReadAllText(string path) : 위와 동일
    • File.ReadAllText(string path, System.Text.Encoding encoding) : 지정된 인코딩으로 읽음. 이하 위와 동일
  • File.WriteAllText : 새 파일을 만들고 지정된 파일에 내용을 쓰고 파일을 닫음. 파일이 이미 있으면 덮어씀.
    • File.WriteAllText(string path, string contents) : 새 파일을 만들고 지정된 파일에 내용을 쓰고 파일을 닫음. 파일이 이미 있으면 덮어씀.
    • File.WriteAllText(string path, string contents, System.Text.Encoding encoding) : 지정된 인코딩으로 작성. 이하 위와 같음.
    • 인코딩 : 정보의 형태나 형식을 변환하는 처리나 처리방식
      • 포맷 방식 즈음으로 이해해도 되려나?
  • TextAsset


Reference

C#을 사용하여 JSON 직렬화 및 역직렬화 - .NET
이 개요에서는 .NET에서 JSON으로 직렬화 및 역직렬화하는 System.Text.Json 네임스페이스 기능에 대해 설명합니다.
https://learn.microsoft.com/ko-kr/dotnet/standard/serialization/system-text-json/overview
스트림 (Stream) 개념 - 닷넷(C#)
프로그램의 입력과 출력 대부분의 소프트웨어는 실행 환경 외부로부터 데이터를 입력 받거나, 자신이 생산...
https://blog.naver.com/PostView.naver?blogId=okcharles&logNo=222502671306&parentCategoryNo=&categoryNo=21&viewDate=&isShowPopularPosts=false&from=postView
객체 직렬화(Serialization) 역직렬화(Deserialization)
객체 직렬화와 관련된 일반적인 사항들은 다음 사이트를 참고한다. http://en.wikipedia.org/wiki/Serialization http://msdn.microsoft.com/ko-kr/library/system.serializableattribute.aspx Serialization(직렬화) : WikiPedia에 나와 있는 정의를 대충(?) 요약하면 다음과 같다. In computer science, in the context of data storage and transmission, serialization is the process of saving an object onto a storage medium (such as a file, or a memory buffer) or to ..
https://oversky.tistory.com/53
객체 직렬화(Serialization) 역직렬화(Deserialization)
객체 직렬화와 관련된 일반적인 사항들은 다음 사이트를 참고한다. http://en.wikipedia.org/wiki/Serialization http://msdn.microsoft.com/ko-kr/library/system.serializableattribute.aspx Serialization(직렬화) : WikiPedia에 나와 있는 정의를 대충(?) 요약하면 다음과 같다. In computer science, in the context of data storage and transmission, serialization is the process of saving an object onto a storage medium (such as a file, or a memory buffer) or to ..
https://oversky.tistory.com/53

유니티 엔진 JsonUtility 다루기 - JSON 읽기
이 포스트에서는 유니티 엔진에서 자체적으로 JSON을 다루게 해주는 JsonUtility를 통해 저장된 JSON 파일을 읽는 법을 배울 것이다. 읽는 사람이 JSON의 구조를 이해하고 있다고 가정하고 작성한다. JSON을 잘 모르면 모질라 재단에서 친절하게 설명하고 있으니 보고 오도록 하자. 자바스크립트도 어느 정도 공부하면 더욱 좋을 것이다. 유니티 엔진을 다루면서 특정 데이터를 보관할 일이 있다. 아이템의 능력치나 기타 유니티 내 스크립트에 하드 코딩하기 껄끄러운 대상은 보통 XML 또는 JSON으로 보관한다. 유니티 엔진에는 자체적으로 JsonUtility 모듈을 가지고 있어 JSON 포맷을 관리할 수 있게 해 준다. 지원하는 기능이 적다는 단점이 있지만 충분히 작은 프로젝트에서는 JsonUtili..
https://nicotina04.tistory.com/211
C# JSON 형태로 데이터 읽기, 쓰기 (생성 포함)
이번에는 C#에서 JSON 형태로 데이터를 읽고 쓰는 방법에 대하여 알아보겠습니다. 환경은 Visual Studio 2019 에서 작업하였습니다. 먼저 라이브러리를 참조 추가해야 하는데 이 곳에서 진행합니다. * JSON 라이브러리 추가하기 Nuget 패키지 관리로 들어간 후 찾아보기 탭으로 들어가면 여러 패키지들이 나타나는데 검색창에 json 이라고 입력 후 Newtonsoft.Json 이라고 되어있는 항목을 클릭합니다. 클릭하면 오른쪽에 현재 프로젝트가 나타나는데 라이브러리를 설치할 프로젝트를 선택하고 설치 버튼을 눌러 설치를 진행합니다. 저는 이미 설치가 되어있어 화면과 살짝 다를 수 있습니다. 설치를 성공적으로 끝냈다면 위와 같이 참조 목록에 Newtonsoft.Json 항목이 추가 될 것입니다...
https://skfkdkdlaos.tistory.com/57

파싱 - 해시넷
토론 | 기여 | 계정 만들기 | 로그인
http://wiki.hash.kr/index.php/파싱
유니티 - JsonUtility로 Json 파싱하기 : (1) 기본
Unity 전체 링크 JsonUtility로 Json 파싱하기 (1) Json Parsing (2) Json Array Parsing (배열 파싱) (3) Array of Objects in Json Array Parsing (배열 안에 있는 오브젝트 배열 파싱) (4) Json Export (파일 출력, 내보내기) *.json 파일을 파싱하여 출력해보자. 먼저 이번에 파싱할 파일(Lotto1.json)은 아래와 같다. { "id":"1", "date":"2002-12-07", "number":[10,23,29,33,37,40], "bonus":16 } 대한민국에서 로또는 2002년 12월 07일(date)에 1회(id)를 시작하였고, 당첨 번호(number)는 10, 23, 29, 33, 37, 40이..
https://bloodstrawberry.tistory.com/753

유니티에서 제이슨(Json)을 사용하는 방법
아직 제이슨을 다뤄본 적이 없는 초보를 위한 Json 강의입니다. 궁금한 사항이나 모르는 부분 등은 댓글로 달아주시면 감사하겠습니다. 블로그를 통해서도 유니티에 대한 다양한 정보를 얻으실 수 있습니다. 블로그 : https://coding-of-today.tistory.com/
https://www.youtube.com/watch?v=-Myy_fRljo0
[유니티 매뉴얼] JSON 직렬화
1. JSON 이란? JSON(제이슨, JavaScript Object Notation)은 이름과 값으로 이루어진 데이터 오브젝트로, 웹이나 네트워크에서 데이터를 주고 받을 때 사용하는 개방형 표준 포멧입니다. JSON 데이터는 텍스트로 되어 있어 읽기 쉽다는 장점을 가지고 있고, 내용을 함축적으로 최소의 정보만을 사용하기 때문에, XML에 비해 용량이 작고, 속도도 빠릅니다. JSON 데이터 기본 형태는 데이터명, 클론(:), 값 순서로 구성되어 있습니다. "데이터명":값 데이터명과 문자열은 ""(큰 따음표)로 감싸야 합니다. "name":"Coderzero" JSON은 다음과같은 데이터형을 지원합니다. 숫자(number) : 정수, 실수, 지수 문자열(string) 불리언(boolean) 객체(obj..
https://coderzero.tistory.com/entry/유니티-매뉴얼-JSON-직렬화
Unity JsonUtility로 MonoBehaviour 저장/로드
JsonUtility.FromJson Json&nbsp;string을&nbsp;받아서&nbsp;새 object를&nbsp;생성해서&nbsp;리턴해...
https://blog.naver.com/PostView.naver?blogId=match-life&logNo=221328936187
[Unity] 유니티 json 데이터 읽기, 파싱, 파서 관련
================================= ================================= ================================= 출처: http://dolphin.ivyro.net/file/mobile/unity_util/tutorial04.html JsonUtility 유니티 5.3 이상부터 JsonUtility를 지원한다. 외부 JSON 라이브러리가 필요 없다. < JsonUtility 멤버 함수 > FromJson : JSON을 오브젝트로 변환한다. 오브젝트를 생성한다. FromJsonOverwrite : JSON을 오브젝트로 변환한다. 오브젝트를 생성하지 않고 값을 변경한다. ToJson : 오브젝트의 public 필드를 JSON으로 변환한다...
https://202psj.tistory.com/1261

File.WriteAllText 메서드 (System.IO)
새 파일을 만들고 파일에 내용을 쓴 다음 파일을 닫습니다. 대상 파일이 이미 있으면 덮어씁니다.
https://learn.microsoft.com/ko-kr/dotnet/api/system.io.file.writealltext?view=net-7.0
File.ReadAllText 메서드 (System.IO)
텍스트 파일을 열고, 파일의 모든 텍스트를 문자열로 읽어 들인 다음에 파일을 닫습니다.
https://learn.microsoft.com/ko-kr/dotnet/api/system.io.file.readalltext?view=net-7.0
텍스트 에셋 - Unity 매뉴얼
텍스트 에셋(Text Assets) 는 임포트한 텍스트 파일의 포맷입니다. 텍스트 파일을 Project 폴더에 드롭하면 텍스트 에셋으로 변환됩니다. 지원되는 텍스트 포맷은 다음과 같습니다.
https://docs.unity3d.com/kr/530/Manual/class-TextAsset.html


Uploaded by N2T

'UnityProjects > Item' 카테고리의 다른 글

아이템 기획  (1) 2023.11.07
Json 연습하기  (1) 2023.11.03