Documentation ¶
Overview ¶
Package ubjson implements encoding and decoding of UBJSON (spec 12). http://ubjson.org/
Most types can be automatically encoded through reflection with the Marshal and Unmarshal functions. Encoders and Decoders additionally provide type specific methods. Custom encodings can be defined by implementing the Value interface. 'ubjson' struct tags can be used to override field names.
b, _ := ubjson.MarshalBlock(8) // [U][8] b, _ = ubjson.MarshalBlock("hello") // [S][U][5][hello] var v interface{} ... b, _ = ubjson.Marshal(v) // ...
Example (CustomValue) ¶
package main import ( "fmt" "github.com/jmank88/ubjson" ) // A CustomValue encodes itself as a fixed length object container. type CustomValue struct { Field1 string FieldA int } func (c *CustomValue) UBJSONType() ubjson.Marker { return ubjson.ObjectStartMarker } func (c *CustomValue) MarshalUBJSON(e *ubjson.Encoder) error { o, err := e.ObjectLen(2) if err != nil { return err } if err := o.EncodeKey("Field1"); err != nil { return err } if err := o.EncodeString(c.Field1); err != nil { return err } if err := o.EncodeKey("FieldA"); err != nil { return err } if err := o.EncodeInt(c.FieldA); err != nil { return err } return o.End() } func (c *CustomValue) UnmarshalUBJSON(d *ubjson.Decoder) error { o, err := d.Object() if err != nil { return err } for o.NextEntry() { k, err := o.DecodeKey() if err != nil { return err } switch k { case "Field1": s, err := o.DecodeString() if err != nil { return err } c.Field1 = s case "FieldA": i, err := o.DecodeInt() if err != nil { return err } c.FieldA = i } } return o.End() } func main() { v := &CustomValue{Field1: "test", FieldA: 42} if b, err := ubjson.MarshalBlock(v); err != nil { fmt.Println("error: " + err.Error()) } else { fmt.Println(string(b)) } }
Output: [{][#][U][2] [U][6][Field1][S][U][4][test] [U][6][FieldA][U][42]
Example (Pair) ¶
package main import ( "fmt" "github.com/jmank88/ubjson" ) // A Int8Vec3 encodes itself as a fixed length, strongly-typed array container. type Int8Vec3 struct { a, b, c int8 } func (iv *Int8Vec3) UBJSONType() ubjson.Marker { return ubjson.ArrayStartMarker } func (iv *Int8Vec3) MarshalUBJSON(e *ubjson.Encoder) error { a, err := e.ArrayType(ubjson.Int8Marker, 3) if err != nil { return err } if err := a.EncodeInt8(iv.a); err != nil { return err } if err := a.EncodeInt8(iv.b); err != nil { return err } if err := a.EncodeInt8(iv.c); err != nil { return err } return a.End() } func (iv *Int8Vec3) UnmarshalUBJSON(d *ubjson.Decoder) error { a, err := d.Array() if err != nil { return err } if i, err := a.DecodeInt8(); err != nil { return err } else { iv.a = i } if i, err := a.DecodeInt8(); err != nil { return err } else { iv.b = i } if i, err := a.DecodeInt8(); err != nil { return err } else { iv.c = i } return a.End() } func main() { iv := &Int8Vec3{a: 100, b: 42, c: -55} if b, err := ubjson.MarshalBlock(iv); err != nil { fmt.Println("error: " + err.Error()) } else { fmt.Println(string(b)) } }
Output: [[][$][i][#][U][3] [100] [42] [-55]
Example (StructAsArray) ¶
package main import ( "fmt" "github.com/jmank88/ubjson" ) // A Nameless struct encodes itself as a fixed length, ordered Array container, // omitting the string names to save space. type Nameless struct { Field1 string FieldA int8 } func (n *Nameless) UBJSONType() ubjson.Marker { return ubjson.ArrayStartMarker } func (n *Nameless) MarshalUBJSON(e *ubjson.Encoder) error { a, err := e.ArrayLen(2) if err != nil { return err } if err := a.EncodeString(n.Field1); err != nil { return err } if err := a.EncodeInt8(n.FieldA); err != nil { return err } return a.End() } func (n *Nameless) UnmarshalUBJSON(d *ubjson.Decoder) error { a, err := d.Array() if err != nil { return err } n.Field1, err = d.DecodeString() if err != nil { return err } n.FieldA, err = d.DecodeInt8() if err != nil { return err } return a.End() } func main() { if b, err := ubjson.MarshalBlock(&Nameless{Field1: "test", FieldA: 42}); err != nil { fmt.Println("error: " + err.Error()) } else { fmt.Println(string(b)) } }
Output: [[][#][U][2] [S][U][4][test] [i][42]
Example (TaggedStruct) ¶
package main import ( "fmt" "github.com/jmank88/ubjson" ) // A TaggedStruct has fields with 'ubjson' tags. type TaggedStruct struct { Field1 string `ubjson:"field1"` FieldA int `json:"ignored" ubjson:"fieldA"` } func main() { v := &TaggedStruct{Field1: "test", FieldA: 42} if b, err := ubjson.MarshalBlock(v); err != nil { fmt.Println("error: " + err.Error()) } else { fmt.Println(string(b)) } }
Output: [{] [U][6][field1][S][U][4][test] [U][6][fieldA][U][42] [}]
Index ¶
- Constants
- func Marshal(v interface{}) ([]byte, error)
- func MarshalBlock(v interface{}) ([]byte, error)
- func Unmarshal(binary []byte, v interface{}) error
- func UnmarshalBlock(block []byte, v interface{}) error
- type ArrayDecoder
- type ArrayEncoder
- type Char
- type Decoder
- func (d *Decoder) Array() (*ArrayDecoder, error)
- func (d *Decoder) Decode(v interface{}) error
- func (d *Decoder) DecodeArray(decodeData func(*ArrayDecoder) error) error
- func (d *Decoder) DecodeBool() (bool, error)
- func (d *Decoder) DecodeChar() (byte, error)
- func (d *Decoder) DecodeFloat32() (float32, error)
- func (d *Decoder) DecodeFloat64() (float64, error)
- func (d *Decoder) DecodeHighPrecNumber() (string, error)
- func (d *Decoder) DecodeInt() (int, error)
- func (d *Decoder) DecodeInt16() (int16, error)
- func (d *Decoder) DecodeInt32() (int32, error)
- func (d *Decoder) DecodeInt64() (int64, error)
- func (d *Decoder) DecodeInt8() (int8, error)
- func (d *Decoder) DecodeObject(decodeData func(*ObjectDecoder) error) error
- func (d *Decoder) DecodeString() (string, error)
- func (d *Decoder) DecodeUInt8() (uint8, error)
- func (d *Decoder) DecodeValue(v Value) error
- func (d *Decoder) Object() (*ObjectDecoder, error)
- type Encoder
- func (e *Encoder) Array() (*ArrayEncoder, error)
- func (e *Encoder) ArrayLen(len int) (*ArrayEncoder, error)
- func (e *Encoder) ArrayType(elemType Marker, len int) (*ArrayEncoder, error)
- func (e *Encoder) Encode(v interface{}) error
- func (e *Encoder) EncodeArray(encodeData func(*Encoder) error) error
- func (e *Encoder) EncodeBool(v bool) error
- func (e *Encoder) EncodeChar(v byte) error
- func (e *Encoder) EncodeFloat32(v float32) error
- func (e *Encoder) EncodeFloat64(v float64) error
- func (e *Encoder) EncodeHighPrecNum(v string) error
- func (e *Encoder) EncodeInt(v int) error
- func (e *Encoder) EncodeInt16(v int16) error
- func (e *Encoder) EncodeInt32(v int32) error
- func (e *Encoder) EncodeInt64(v int64) error
- func (e *Encoder) EncodeInt8(v int8) error
- func (e *Encoder) EncodeNoOp() error
- func (e *Encoder) EncodeNull() error
- func (e *Encoder) EncodeObject(encodeData func(*Encoder) error) error
- func (e *Encoder) EncodeString(v string) error
- func (e *Encoder) EncodeUInt8(v uint8) error
- func (e *Encoder) EncodeValue(v Value) error
- func (e *Encoder) Object() (*ObjectEncoder, error)
- func (e *Encoder) ObjectLen(len int) (*ObjectEncoder, error)
- func (e *Encoder) ObjectType(valType Marker, len int) (*ObjectEncoder, error)
- type HighPrecNumber
- type Marker
- type ObjectDecoder
- type ObjectEncoder
- type Value
Examples ¶
Constants ¶
const MaxCollectionAlloc = 1 << 24
MaxCollectionAlloc is the default maximum collection capacity allocation. Can be overridden via Decoder.MaxCollectionAlloc.
Variables ¶
This section is empty.
Functions ¶
func Marshal ¶
Marshal encodes a value into UBJSON. Types implementing Value will be encoded with their UBJSONType and MarshalUBJSON methods.
func MarshalBlock ¶
MarshalBlock encodes a value into UBJSON block-notation. Types implementing Value will be encoded with their UBJSONType and MarshalUBJSON methods.
Example ¶
package main import ( "fmt" "github.com/jmank88/ubjson" ) func main() { if b, err := ubjson.MarshalBlock(8); err != nil { fmt.Println("error: " + err.Error()) } else { fmt.Println(string(b)) } }
Output: [U][8]
Example (Array) ¶
package main import ( "fmt" "github.com/jmank88/ubjson" ) func main() { if b, err := ubjson.MarshalBlock([]byte("testbytes")); err != nil { fmt.Println("error: " + err.Error()) } else { fmt.Println(string(b)) } }
Output: [[][$][U][#][U][9] [116] [101] [115] [116] [98] [121] [116] [101] [115]
Example (Ints) ¶
package main import ( "fmt" "github.com/jmank88/ubjson" ) func main() { if b, err := ubjson.MarshalBlock(8); err != nil { fmt.Println("error: " + err.Error()) } else { fmt.Println(string(b)) } if b, err := ubjson.MarshalBlock(-42); err != nil { fmt.Println("error: " + err.Error()) } else { fmt.Println(string(b)) } if b, err := ubjson.MarshalBlock(256); err != nil { fmt.Println("error: " + err.Error()) } else { fmt.Println(string(b)) } }
Output: [U][8] [i][-42] [I][256]
Example (Object) ¶
package main import ( "fmt" "github.com/jmank88/ubjson" ) func main() { type object struct { Str string Int int64 Bytes []byte } o := &object{Str: "str", Int: 45678, Bytes: []byte("test")} if b, err := ubjson.MarshalBlock(o); err != nil { fmt.Println("error: " + err.Error()) } else { fmt.Println(string(b)) } }
Output: [{] [U][3][Str][S][U][3][str] [U][3][Int][L][45678] [U][5][Bytes][[][$][U][#][U][4] [116] [101] [115] [116] [}]
func Unmarshal ¶
Unmarshal decodes a value from UBJSON. Types implementing Value will be decoded via their UBJSONType and UnmarshalUBJSON methods.
func UnmarshalBlock ¶
UnmarshalBlock decodes a value from UBJSON block-notation. Types implementing Value will be encoded with their UBJSONType and MarshalUBJSON methods.
Types ¶
type ArrayDecoder ¶
type ArrayDecoder struct { Decoder // Element type, or 0 if not present. ElemType Marker // Number of elements, or -1 if not present. Len int // contains filtered or unexported fields }
An ArrayDecoder is a Decoder for array container elements.
func (*ArrayDecoder) End ¶
func (a *ArrayDecoder) End() error
End completes array decoding and must be called. It may return errors (1) deferred from element decoding, (2) from a missing array end marker, or (3) from a length vs. count mismatch.
func (*ArrayDecoder) NextElem ¶
func (a *ArrayDecoder) NextElem() bool
NextElem returns true when there is another element to decode, or false if the end of the array has been reached or an error is encountered, in which case it will be returned by the End method.
type ArrayEncoder ¶
type ArrayEncoder struct { Encoder // contains filtered or unexported fields }
An ArrayEncoder supplements an Encoder with an End() method, and performs validation and optimization of array elements. Callers must finish with a call to End().
type Char ¶
type Char byte
A Char is a byte which is encoded as 'C' instead of 'U'. Must be <=127.
Example ¶
package main import ( "fmt" "github.com/jmank88/ubjson" ) func main() { // Single `byte`s (and `uint8`s) normally use the UInt8 marker. if b, err := ubjson.MarshalBlock(byte('a')); err != nil { fmt.Println("error: " + err.Error()) } else { fmt.Println(string(b)) } // The `Char` type uses the Char marker instead. if b, err := ubjson.MarshalBlock(ubjson.Char('a')); err != nil { fmt.Println("error: " + err.Error()) } else { fmt.Println(string(b)) } }
Output: [U][97] [C][a]
type Decoder ¶
type Decoder struct { // Limits the capacity of allocated collections and returns errors rather // than risking waste or panicking on unreasonable/malicious input. // Example: "[[][$][T][#][l][999999999999999999]". // New Decoders default to package const MaxCollectionAlloc. MaxCollectionAlloc int // contains filtered or unexported fields }
Decoder provides methods for decoding UBJSON data types.
func NewBlockDecoder ¶
NewBlockDecoder returns a new block-notation Decoder.
func (*Decoder) Array ¶
func (d *Decoder) Array() (*ArrayDecoder, error)
Array begins decoding an array, and returns a specialized decoder for array elements.
func (*Decoder) Decode ¶
Decode decodes a value into v by delegating to the appropriate type-specific method. Recognizes the special types Char and HighPrecNumber to distinguish from backing types.
func (*Decoder) DecodeArray ¶
func (d *Decoder) DecodeArray(decodeData func(*ArrayDecoder) error) error
DecodeArray decodes an array container.
func (*Decoder) DecodeBool ¶
DecodeBool decodes a 'T' or 'F' marker.
func (*Decoder) DecodeChar ¶
DecodeChar decodes a 'C' value into a byte.
func (*Decoder) DecodeFloat32 ¶
DecodeFloat32 decodes an 'f' value into a float32.
func (*Decoder) DecodeFloat64 ¶
DecodeFloat64 decodes an 'F' value into a float64.
func (*Decoder) DecodeHighPrecNumber ¶
DecodeHighPrecNumber decodes an 'H' value into a string.
func (*Decoder) DecodeInt16 ¶
DecodeInt16 decodes an 'I' value into an int16.
func (*Decoder) DecodeInt32 ¶
DecodeInt32 decodes an 'l' value into an int32.
func (*Decoder) DecodeInt64 ¶
DecodeInt64 decodes an 'L' value into an int64.
func (*Decoder) DecodeInt8 ¶
DecodeInt8 decodes an 'i' value into an int8.
func (*Decoder) DecodeObject ¶
func (d *Decoder) DecodeObject(decodeData func(*ObjectDecoder) error) error
DecodeObject decodes an object container.
func (*Decoder) DecodeString ¶
DecodeString decodes an 'S' value into a string.
func (*Decoder) DecodeUInt8 ¶
DecodeUInt8 decodes a 'U' value into a uint8.
func (*Decoder) DecodeValue ¶
DecodeValue decodes the next value into v.
func (*Decoder) Object ¶
func (d *Decoder) Object() (*ObjectDecoder, error)
Object begins decoding an object, and returns a specialized decoder for object entries.
type Encoder ¶
type Encoder struct {
// contains filtered or unexported fields
}
Encoder provides methods for encoding UBJSON data types.
func NewBlockEncoder ¶
NewBlockEncoder returns a new block-notation Encoder.
func (*Encoder) Array ¶
func (e *Encoder) Array() (*ArrayEncoder, error)
Array method encoding an array container.
func (*Encoder) ArrayLen ¶
func (e *Encoder) ArrayLen(len int) (*ArrayEncoder, error)
ArrayLen begins encoding an array container with a specified length.
func (*Encoder) ArrayType ¶
func (e *Encoder) ArrayType(elemType Marker, len int) (*ArrayEncoder, error)
ArrayType begins encoding a strongly-typed array container with a specified length. When encoding a single byte element type, actual elements are optimized away, and End() must be called immediately.
func (*Encoder) Encode ¶
Encode encodes v into universal binary json. Types implementing Value will be encoded via their MarshalUBJSON method.
func (*Encoder) EncodeArray ¶
EncodeArray encodes an array container.
func (*Encoder) EncodeBool ¶
EncodeBool encodes the true (T) or false (F) Marker.
func (*Encoder) EncodeChar ¶
EncodeChar encodes a byte as a 'C'.
func (*Encoder) EncodeFloat32 ¶
EncodeFloat32 encodes a float32 as an 'f'.
func (*Encoder) EncodeFloat64 ¶
EncodeFloat64 encodes a float64 as an 'F'.
func (*Encoder) EncodeHighPrecNum ¶
EncodeHighPrecNum encodes a string v as a high precision number 'H'.
func (*Encoder) EncodeInt ¶
EncodeInt encodes an int in the smallest possible integer format (U,i,L,l,L).
func (*Encoder) EncodeInt16 ¶
EncodeInt16 encodes an int16 as an 'I'.
func (*Encoder) EncodeInt32 ¶
EncodeInt32 encodes an int32 as an 'l'.
func (*Encoder) EncodeInt64 ¶
EncodeInt64 encodes an int64 as an 'L'.
func (*Encoder) EncodeInt8 ¶
EncodeInt8 encodes an int8 as an 'i'.
func (*Encoder) EncodeNoOp ¶
EncodeNoOp encodes the NoOp valType.
func (*Encoder) EncodeNull ¶
EncodeNull encodes the null valType.
func (*Encoder) EncodeObject ¶
EncodeObject encodes an object container.
func (*Encoder) EncodeString ¶
EncodeString encodes a string as a 'S'.
func (*Encoder) EncodeUInt8 ¶
EncodeUInt8 encodes a uint8 as a (U).
func (*Encoder) EncodeValue ¶
EncodeValue encodes the Value v, using UBJSONType and UnmarshalUBJSON.
func (*Encoder) Object ¶
func (e *Encoder) Object() (*ObjectEncoder, error)
Object begins encoding an object container.
func (*Encoder) ObjectLen ¶
func (e *Encoder) ObjectLen(len int) (*ObjectEncoder, error)
ObjectLen begins encoding an object container with a specified length.
func (*Encoder) ObjectType ¶
func (e *Encoder) ObjectType(valType Marker, len int) (*ObjectEncoder, error)
ObjectType begins encoding a strongly-typed object container with a specified length.
type HighPrecNumber ¶
type HighPrecNumber string
A HighPrecNumber is a decimal string of arbitrary precision, which is encoded with 'H' instead of 'S'.
Example ¶
package main import ( "fmt" "github.com/jmank88/ubjson" ) func main() { number := "1234567890.657483921" if b, err := ubjson.MarshalBlock(number); err != nil { fmt.Println("error: " + err.Error()) } else { fmt.Println(string(b)) } hNumber := ubjson.HighPrecNumber(number) if b, err := ubjson.MarshalBlock(hNumber); err != nil { fmt.Println("error: " + err.Error()) } else { fmt.Println(string(b)) } }
Output: [S][U][20][1234567890.657483921] [H][U][20][1234567890.657483921]
type Marker ¶
type Marker byte
A Marker is a single byte UBJSON marker.
const ( NullMarker Marker = 'Z' NoOpMarker Marker = 'N' TrueMarker Marker = 'T' FalseMarker Marker = 'F' UInt8Marker Marker = 'U' Int8Marker Marker = 'i' Int16Marker Marker = 'I' Int32Marker Marker = 'l' Int64Marker Marker = 'L' Float32Marker Marker = 'd' Float64Marker Marker = 'D' HighPrecNumMarker Marker = 'H' CharMarker Marker = 'C' StringMarker Marker = 'S' )
Value Type Markers
type ObjectDecoder ¶
type ObjectDecoder struct { Decoder // Value type, or 0 if none included. ValType Marker // Number of entries, or -1 if unspecified. Len int // contains filtered or unexported fields }
An ObjectDecoder supplements a Decoder with NextEntry(), DecodeKey(), and End() methods. Callers must alternate decoding keys and values for either Len entries or until NextEntry() returns false, and finish with End().
func (*ObjectDecoder) DecodeKey ¶
func (o *ObjectDecoder) DecodeKey() (string, error)
DecodeKey reads an object key.
func (*ObjectDecoder) End ¶
func (o *ObjectDecoder) End() error
End completes object decoding and must be called. It may return errors (1) deferred from entry decoding, (2) from a missing object end marker, or (3) from a length vs. count mismatch.
func (*ObjectDecoder) NextEntry ¶
func (o *ObjectDecoder) NextEntry() bool
NextEntry returns true if more entries are expected, or false if the end has been reached or an error was encountered, in which case End() will return the deferred error.
type ObjectEncoder ¶
type ObjectEncoder struct { Encoder // contains filtered or unexported fields }
An ObjectEncoder supplements an Encoder with EncodeKey() and End() methods, and performs validation and optimization of object Values. Callers must alternate Key() and Encode*() methods for the specified number of entries and finish with End().
func (*ObjectEncoder) EncodeKey ¶
func (o *ObjectEncoder) EncodeKey(key string) error
EncodeKey encodes an object key.
func (*ObjectEncoder) End ¶
func (o *ObjectEncoder) End() error
End checks the length or writes an end maker.
type Value ¶
type Value interface { // The type marker for this kind of value. Must always return the same value. UBJSONType() Marker // Marshals the value to an encoder using containers and primitive values. MarshalUBJSON(*Encoder) error // Unmarshals containers and primitive values from a decoder into the value. UnmarshalUBJSON(*Decoder) error }
The Value interface defines a custom encoding.