시작하기
값을 바이트로, 타입을 JSON으로 담기.
바이트로 담기
ByteWriter가 버퍼를 만들고, ByteReader가 같은 순서로 읽어 돌려줍니다.
using Udonite.Serialization;
byte[] payload = new ByteWriter()
.WriteInt32(playerId)
.WriteString(name)
.ToArray();
ByteReader reader = new ByteReader(payload);
int id = reader.ReadInt32();
string readName = reader.ReadString();
둘 다 Udonite Net의 메시지 가이드에 자세히 다뤄져 있습니다 — 애초에 그걸 위해 만들어졌으니까요. NetworkEvent의 Serialize(ByteWriter)/Deserialize(ByteReader)가 그것입니다. 하지만 이 둘 자체는 네트워크 전용이 아닙니다. 양쪽 끝을 직접 소유하는, 압축되고 자기완결적인 바이너리 형태가 필요하다면 어디든 써도 됩니다 — 저장 포맷이든, 파일이든.
끝을 넘어서 읽어도 예외가 나지 않습니다. 로그를 남기고 해당 타입의 기본값을 반환합니다. Udon에는 되감을 예외 처리가 없고, 손상되거나 잘린 버퍼가 읽는 쪽 behaviour를 함께 끌고 내려가서는 안 되기 때문입니다.
타입을 JSON으로 담기
타입은 IJsonSerializable을 구현하는 것으로 참여합니다 — 직접 ToJson()/FromJson()을 작성합니다. Udon에는 그 순회를 대신해줄 리플렉션이 없기 때문입니다.
using Udonite.Serialization;
using VRC.SDK3.Data;
public class Player : IJsonSerializable
{
public string Name;
public int Score;
public DataToken ToJson()
{
DataDictionary dict = new DataDictionary();
dict.Add("name", Name);
dict.Add("score", Score);
return dict;
}
public void FromJson(DataToken token)
{
DataDictionary dict = token.DataDictionary;
Name = dict["name"].String;
Score = (int)dict["score"].Double;
}
}
숫자는 .Int가 아니라 반드시 .Double로 읽으세요. 정수로 적었더라도 JSON 숫자는 모두 TokenType.Double로 파싱되어 돌아옵니다 — .Int는 거기서 예외를 던집니다. 이건 VRCJson 자체의 특성이고, 이 패키지가 감춰줄 수 있는 게 아닙니다.
직렬화·역직렬화를 호출하는 쪽에는 DataToken이 전혀 등장하지 않습니다.
Player player = new Player { Name = "Ada", Score = 42 };
string json = Json.Serialize(player); // {"name":"Ada","score":42}, 실패하면 null
Player restored = Json.Deserialize<Player>(json); // 새 Player, 잘못된 JSON이면 null
Deserialize<T>는 인스턴스를 직접 만듭니다. T에는 매개변수 없는 생성자가 필요합니다(where T : new()). 이건 런타임이 아니라 컴파일러가 호출 지점에서 해결하는 제약으로, 다른 제네릭 제약과 다를 바 없습니다. 리플렉션이 아니며, Udon에 리플렉션이 없어도 동작합니다.
자동으로 조사되는 건 아무것도 없습니다. ToJson()이 언급하지 않은 필드는 전송되지 않고, IJsonSerializable을 아예 구현하지 않은 타입은 Serialize<T>에 대해 컴파일 오류가 됩니다 — 런타임에 일부만 직렬화된 객체가 되는 일은 없습니다.
정해진 타입 없이 JSON 만들기
IJsonSerializable 없이 즉석에서 조립하는 JSON을 위해, DataToken을 직접 다루는 비제네릭 오버로드가 있습니다.
DataDictionary dict = new DataDictionary();
dict.Add("ok", true);
string json = Json.Serialize(dict); // 또는 Json.Serialize(dict, pretty: true)
DataToken? parsed = Json.Deserialize(json);
DataToken이 꼭 필요한 곳은 여기뿐입니다. VRChat 자신의 JSON 값 모델 그 자체이기 때문입니다 — 객체는 DataDictionary, 배열은 DataList, 그보다 단순한 것은 스칼라 토큰으로 대응합니다.
다음으로 읽을 것
레퍼런스는 양쪽 모두의 전체 멤버 목록입니다.