Reference

Every member of ByteWriter, ByteReader, Json and IJsonSerializable.

Updated 2026-09-11

Everything lives in Udonite.Serialization.

ByteWriter

new ByteWriter()             // default starting capacity
new ByteWriter(64)           // starting capacity in bytes; grows past it as needed
Member Writes
WriteByte(byte) one byte
WriteBoolean(bool), WriteChar(char) fixed-width
WriteInt16, WriteUInt16, WriteInt32, WriteUInt32, WriteSingle, WriteDouble fixed-width, System.BitConverter-backed
WriteString(string) length-prefixed (0 for null), one character at a time
WriteBytes(byte[]) length-prefixed raw bytes — the seam a nested payload rides through
WriteVector2, WriteVector3, WriteQuaternion component by component
WriteLength(int) a count in as few bytes as it needs — one byte up to 127, two up to 16383
Position { get; } bytes written so far
Reset() rewinds to empty without allocating a new buffer
ToArray() a right-sized copy — the over-allocated tail is never part of it

Every Write method returns this, so calls chain: new ByteWriter().WriteInt32(1).WriteString("a").

Deliberately a core, not a full mirror of System.BitConverter. No 64-bit integers, no 8-bit-signed, no 16-bit-narrower-than-short, no Vector2Int. A reached class is compiled whole, and every method it declares costs heap for the life of the program — the surface here is exactly what a payload plausibly carries.

ByteReader

new ByteReader(bytes)
Member Reads
ReadByte() one byte
ReadBoolean(), ReadChar() fixed-width
ReadInt16, ReadUInt16, ReadInt32, ReadUInt32, ReadSingle, ReadDouble fixed-width
ReadString() a WriteString payload back
ReadBytes() a WriteBytes payload back
ReadVector2, ReadVector3, ReadQuaternion component by component
ReadLength() a WriteLength count back
Position { get; }, Length { get; }, LengthRemaining { get; } where the cursor is, how big the buffer is, and what is left
SetBuffer(byte[]) reuses this reader on a different buffer, cursor reset to the start

A read past the end logs and returns the type's default rather than throwing. Exception handling is unproven in Udonite, and a malformed or truncated buffer must not take the reading behaviour down with it. Read in the same order you wrote, and read everything you wrote — nothing here can tell you the shape was wrong, only that a read ran out of bytes.

Json

Member Does
Serialize<T>(T) Packs T to JSON, by way of its own ToJson(). Null if T is null or VRCJson refuses it
Deserialize<T>(string) Parses JSON, builds a new T (where T : class, IJsonSerializable, new()), fills it by way of FromJson. Null on malformed JSON
Serialize(DataToken), Serialize(DataToken, bool pretty) The low-level form, for JSON built ad hoc with no fixed type behind it
Deserialize(string) Returns a DataToken? directly, the same escape hatch in reverse

Null on failure throughout, never a bool and an out parameter.

No reflection-based Serialize<T> that walks an arbitrary type's fields. Udon has no reflection at all — confirmed directly against the compiler, not assumed. Deserialize<T>'s where T : new() is not reflection either: it is a constraint the C# compiler resolves at the call site, so it compiles even though nothing here could call Activator.CreateInstance.

Every JSON number parses as TokenType.Double, even a bare integer. {"score": 42} parses to a token whose .Int throws — only .Double (cast to whatever you need) reads it. This is a fact about VRCJson itself, not something this wrapper changes.

IJsonSerializable

Member Does
DataToken ToJson() Packs this instance, typically into a DataDictionary
void FromJson(DataToken token) Fills this instance from what ToJson produced

A field either method does not mention is never sent and never filled — nothing here inspects a type's members automatically. FromJson mutates the instance it is called on rather than returning a new one, the same way NetworkEvent.Deserialize does in Udonite Net: nothing here can construct an arbitrary type without either new() or a caller who already made one.

Something went wrong Reload