msgpack

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 29, 2021 License: BSD-2-Clause Imports: 18 Imported by: 4

README

MessagePack encoding for Golang

Build Status GoDoc

Supports:

API docs: https://godoc.org/github.com/vmihailenco/msgpack. Examples: https://godoc.org/github.com/vmihailenco/msgpack#pkg-examples.

Installation

This project uses Go Modules and semantic import versioning since v4:

go mod init github.com/my/repo
go get github.com/fox-one/msgpack

Quickstart

import "github.com/fox-one/msgpack"

func ExampleMarshal() {
	type Item struct {
		Foo string
	}

	b, err := msgpack.Marshal(&Item{Foo: "bar"})
	if err != nil {
		panic(err)
	}

	var item Item
	err = msgpack.Unmarshal(b, &item)
	if err != nil {
		panic(err)
	}
	fmt.Println(item.Foo)
	// Output: bar
}

Benchmark

BenchmarkStructVmihailencoMsgpack-4   	  200000	     12814 ns/op	    2128 B/op	      26 allocs/op
BenchmarkStructUgorjiGoMsgpack-4      	  100000	     17678 ns/op	    3616 B/op	      70 allocs/op
BenchmarkStructUgorjiGoCodec-4        	  100000	     19053 ns/op	    7346 B/op	      23 allocs/op
BenchmarkStructJSON-4                 	   20000	     69438 ns/op	    7864 B/op	      26 allocs/op
BenchmarkStructGOB-4                  	   10000	    104331 ns/op	   14664 B/op	     278 allocs/op

Howto

Please go through examples to get an idea how to use this package.

See also

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Marshal

func Marshal(v interface{}) ([]byte, error)

Marshal returns the MessagePack encoding of v.

Example
package main

import (
	"fmt"

	"github.com/fox-one/msgpack"
)

func main() {
	type Item struct {
		Foo string
	}

	b, err := msgpack.Marshal(&Item{Foo: "bar"})
	if err != nil {
		panic(err)
	}

	var item Item
	err = msgpack.Unmarshal(b, &item)
	if err != nil {
		panic(err)
	}
	fmt.Println(item.Foo)
}
Output:

bar
Example (AsArray)
package main

import (
	"bytes"
	"fmt"

	"github.com/fox-one/msgpack"
)

func main() {
	type Item struct {
		_msgpack struct{} `msgpack:",asArray"`
		Foo      string
		Bar      string
	}

	var buf bytes.Buffer
	enc := msgpack.NewEncoder(&buf)
	err := enc.Encode(&Item{Foo: "foo", Bar: "bar"})
	if err != nil {
		panic(err)
	}

	dec := msgpack.NewDecoder(&buf)
	v, err := dec.DecodeInterface()
	if err != nil {
		panic(err)
	}
	fmt.Println(v)
}
Output:

[foo bar]
Example (MapStringInterface)
package main

import (
	"fmt"

	"github.com/fox-one/msgpack"
)

func main() {
	in := map[string]interface{}{"foo": 1, "hello": "world"}
	b, err := msgpack.Marshal(in)
	if err != nil {
		panic(err)
	}

	var out map[string]interface{}
	err = msgpack.Unmarshal(b, &out)
	if err != nil {
		panic(err)
	}

	fmt.Println("foo =", out["foo"])
	fmt.Println("hello =", out["hello"])

}
Output:

foo = 1
hello = world
Example (OmitEmpty)
package main

import (
	"fmt"

	"github.com/fox-one/msgpack"
)

func main() {
	type Item struct {
		Foo string
		Bar string
	}

	item := &Item{
		Foo: "hello",
	}
	b, err := msgpack.Marshal(item)
	if err != nil {
		panic(err)
	}
	fmt.Printf("item: %q\n", b)

	type ItemOmitEmpty struct {
		_msgpack struct{} `msgpack:",omitempty"`
		Foo      string
		Bar      string
	}

	itemOmitEmpty := &ItemOmitEmpty{
		Foo: "hello",
	}
	b, err = msgpack.Marshal(itemOmitEmpty)
	if err != nil {
		panic(err)
	}
	fmt.Printf("item2: %q\n", b)

}
Output:

item: "\x82\xa3Foo\xa5hello\xa3Bar\xa0"
item2: "\x81\xa3Foo\xa5hello"

func Register

func Register(value interface{}, enc encoderFunc, dec decoderFunc)

Register registers encoder and decoder functions for a value. This is low level API and in most cases you should prefer implementing Marshaler/CustomEncoder and Unmarshaler/CustomDecoder interfaces.

func RegisterExt

func RegisterExt(id int8, value interface{})

RegisterExt records a type, identified by a value for that type, under the provided id. That id will identify the concrete type of a value sent or received as an interface variable. Only types that will be transferred as implementations of interface values need to be registered. Expecting to be used only during initialization, it panics if the mapping between types and ids is not a bijection.

Example
package main

import (
	"encoding/binary"
	"fmt"
	"time"

	"github.com/fox-one/msgpack"
)

func init() {
	msgpack.RegisterExt(1, (*EventTime)(nil))
}

// https://github.com/fluent/fluentd/wiki/Forward-Protocol-Specification-v1#eventtime-ext-format
type EventTime struct {
	time.Time
}

var _ msgpack.Marshaler = (*EventTime)(nil)
var _ msgpack.Unmarshaler = (*EventTime)(nil)

func (tm *EventTime) MarshalMsgpack() ([]byte, error) {
	b := make([]byte, 8)
	binary.BigEndian.PutUint32(b, uint32(tm.Unix()))
	binary.BigEndian.PutUint32(b[4:], uint32(tm.Nanosecond()))
	return b, nil
}

func (tm *EventTime) UnmarshalMsgpack(b []byte) error {
	if len(b) == 1 && b[0] == 0xc0 {
		return nil
	}
	if len(b) != 8 {
		return fmt.Errorf("invalid data length: got %d, wanted 8", len(b))
	}
	sec := binary.BigEndian.Uint32(b)
	usec := binary.BigEndian.Uint32(b[4:])
	tm.Time = time.Unix(int64(sec), int64(usec))
	return nil
}

func main() {
	b, err := msgpack.Marshal(&EventTime{time.Unix(123456789, 123)})
	if err != nil {
		panic(err)
	}

	var v interface{}
	err = msgpack.Unmarshal(b, &v)
	if err != nil {
		panic(err)
	}
	fmt.Println(v.(*EventTime).UTC())

	tm := new(EventTime)
	err = msgpack.Unmarshal(b, tm)
	if err != nil {
		panic(err)
	}
	fmt.Println(tm.UTC())

}
Output:

1973-11-29 21:33:09.000000123 +0000 UTC
1973-11-29 21:33:09.000000123 +0000 UTC

func Unmarshal

func Unmarshal(data []byte, v interface{}) error

Unmarshal decodes the MessagePack-encoded data and stores the result in the value pointed to by v.

Types

type CustomDecoder

type CustomDecoder interface {
	DecodeMsgpack(*Decoder) error
}

type CustomEncoder

type CustomEncoder interface {
	EncodeMsgpack(*Encoder) error
}
Example
package main

import (
	"fmt"

	"github.com/fox-one/msgpack"
)

type customStruct struct {
	S string
	N int
}

var _ msgpack.CustomEncoder = (*customStruct)(nil)
var _ msgpack.CustomDecoder = (*customStruct)(nil)

func (s *customStruct) EncodeMsgpack(enc *msgpack.Encoder) error {
	return enc.EncodeMulti(s.S, s.N)
}

func (s *customStruct) DecodeMsgpack(dec *msgpack.Decoder) error {
	return dec.DecodeMulti(&s.S, &s.N)
}

func main() {
	b, err := msgpack.Marshal(&customStruct{S: "hello", N: 42})
	if err != nil {
		panic(err)
	}

	var v customStruct
	err = msgpack.Unmarshal(b, &v)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%#v", v)
}
Output:

msgpack_test.customStruct{S:"hello", N:42}

type Decoder

type Decoder struct {
	// contains filtered or unexported fields
}

A Decoder reads and decodes MessagePack values from an input stream.

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

NewDecoder returns a new decoder that reads from r.

The decoder introduces its own buffering and may read data from r beyond the MessagePack values requested. Buffering can be disabled by passing a reader that implements io.ByteScanner interface.

func (*Decoder) Buffered

func (d *Decoder) Buffered() io.Reader

Buffered returns a reader of the data remaining in the Decoder's buffer. The reader is valid until the next call to Decode.

func (*Decoder) Decode

func (d *Decoder) Decode(v interface{}) error

func (*Decoder) DecodeArrayLen

func (d *Decoder) DecodeArrayLen() (int, error)

DecodeArrayLen decodes array length. Length is -1 when array is nil.

func (*Decoder) DecodeBool

func (d *Decoder) DecodeBool() (bool, error)

func (*Decoder) DecodeBytes

func (d *Decoder) DecodeBytes() ([]byte, error)

func (*Decoder) DecodeBytesLen

func (d *Decoder) DecodeBytesLen() (int, error)

func (*Decoder) DecodeDuration

func (d *Decoder) DecodeDuration() (time.Duration, error)

func (*Decoder) DecodeExtHeader

func (d *Decoder) DecodeExtHeader() (typeID int8, length int, err error)

func (*Decoder) DecodeFloat32

func (d *Decoder) DecodeFloat32() (float32, error)

func (*Decoder) DecodeFloat64

func (d *Decoder) DecodeFloat64() (float64, error)

DecodeFloat64 decodes msgpack float32/64 into Go float64.

func (*Decoder) DecodeInt

func (d *Decoder) DecodeInt() (int, error)

func (*Decoder) DecodeInt16

func (d *Decoder) DecodeInt16() (int16, error)

func (*Decoder) DecodeInt32

func (d *Decoder) DecodeInt32() (int32, error)

func (*Decoder) DecodeInt64

func (d *Decoder) DecodeInt64() (int64, error)

DecodeInt64 decodes msgpack int8/16/32/64 and uint8/16/32/64 into Go int64.

func (*Decoder) DecodeInt8

func (d *Decoder) DecodeInt8() (int8, error)

func (*Decoder) DecodeInterface

func (d *Decoder) DecodeInterface() (interface{}, error)

DecodeInterface decodes value into interface. It returns following types:

  • nil,
  • bool,
  • int8, int16, int32, int64,
  • uint8, uint16, uint32, uint64,
  • float32 and float64,
  • string,
  • []byte,
  • slices of any of the above,
  • maps of any of the above.

DecodeInterface should be used only when you don't know the type of value you are decoding. For example, if you are decoding number it is better to use DecodeInt64 for negative numbers and DecodeUint64 for positive numbers.

func (*Decoder) DecodeInterfaceLoose

func (d *Decoder) DecodeInterfaceLoose() (interface{}, error)

DecodeInterfaceLoose is like DecodeInterface except that:

  • int8, int16, and int32 are converted to int64,
  • uint8, uint16, and uint32 are converted to uint64,
  • float32 is converted to float64.

func (*Decoder) DecodeMap

func (d *Decoder) DecodeMap() (interface{}, error)

func (*Decoder) DecodeMapLen

func (d *Decoder) DecodeMapLen() (int, error)

DecodeMapLen decodes map length. Length is -1 when map is nil.

func (*Decoder) DecodeMulti

func (d *Decoder) DecodeMulti(v ...interface{}) error

func (*Decoder) DecodeNil

func (d *Decoder) DecodeNil() error

func (*Decoder) DecodeSlice

func (d *Decoder) DecodeSlice() ([]interface{}, error)

func (*Decoder) DecodeString

func (d *Decoder) DecodeString() (string, error)

func (*Decoder) DecodeTime

func (d *Decoder) DecodeTime() (time.Time, error)

func (*Decoder) DecodeUint

func (d *Decoder) DecodeUint() (uint, error)

func (*Decoder) DecodeUint16

func (d *Decoder) DecodeUint16() (uint16, error)

func (*Decoder) DecodeUint32

func (d *Decoder) DecodeUint32() (uint32, error)

func (*Decoder) DecodeUint64

func (d *Decoder) DecodeUint64() (uint64, error)

DecodeUint64 decodes msgpack int8/16/32/64 and uint8/16/32/64 into Go uint64.

func (*Decoder) DecodeUint8

func (d *Decoder) DecodeUint8() (uint8, error)

func (*Decoder) DecodeValue

func (d *Decoder) DecodeValue(v reflect.Value) error

func (*Decoder) DisallowUnknownFields

func (d *Decoder) DisallowUnknownFields()

DisallowUnknownFields causes the Decoder to return an error when the destination is a struct and the input contains object keys which do not match any non-ignored, exported fields in the destination.

func (*Decoder) PeekCode

func (d *Decoder) PeekCode() (codes.Code, error)

PeekCode returns the next MessagePack code without advancing the reader. Subpackage msgpack/codes contains list of available codes.

func (*Decoder) Query

func (d *Decoder) Query(query string) ([]interface{}, error)

Query extracts data specified by the query from the msgpack stream skipping any other data. Query consists of map keys and array indexes separated with dot, e.g. key1.0.key2.

Example
package main

import (
	"bytes"
	"fmt"

	"github.com/fox-one/msgpack"
)

func main() {
	b, err := msgpack.Marshal([]map[string]interface{}{
		{"id": 1, "attrs": map[string]interface{}{"phone": 12345}},
		{"id": 2, "attrs": map[string]interface{}{"phone": 54321}},
	})
	if err != nil {
		panic(err)
	}

	dec := msgpack.NewDecoder(bytes.NewBuffer(b))
	values, err := dec.Query("*.attrs.phone")
	if err != nil {
		panic(err)
	}
	fmt.Println("phones are", values)

	dec.Reset(bytes.NewBuffer(b))
	values, err = dec.Query("1.attrs.phone")
	if err != nil {
		panic(err)
	}
	fmt.Println("2nd phone is", values[0])
}
Output:

phones are [12345 54321]
2nd phone is 54321

func (*Decoder) Reset

func (d *Decoder) Reset(r io.Reader)

Reset discards any buffered data, resets all state, and switches the buffered reader to read from r.

func (*Decoder) SetDecodeMapFunc

func (d *Decoder) SetDecodeMapFunc(fn func(*Decoder) (interface{}, error))
Example
package main

import (
	"bytes"
	"fmt"

	"github.com/fox-one/msgpack"
)

func main() {
	buf := new(bytes.Buffer)

	enc := msgpack.NewEncoder(buf)
	in := map[string]string{"hello": "world"}
	err := enc.Encode(in)
	if err != nil {
		panic(err)
	}

	dec := msgpack.NewDecoder(buf)

	// Causes decoder to produce map[string]string instead of map[string]interface{}.
	dec.SetDecodeMapFunc(func(d *msgpack.Decoder) (interface{}, error) {
		n, err := d.DecodeMapLen()
		if err != nil {
			return nil, err
		}

		m := make(map[string]string, n)
		for i := 0; i < n; i++ {
			mk, err := d.DecodeString()
			if err != nil {
				return nil, err
			}

			mv, err := d.DecodeString()
			if err != nil {
				return nil, err
			}

			m[mk] = mv
		}
		return m, nil
	})

	out, err := dec.DecodeInterface()
	if err != nil {
		panic(err)
	}
	fmt.Printf("%#v", out)
}
Output:

map[string]string{"hello":"world"}

func (*Decoder) Skip

func (d *Decoder) Skip() error

Skip skips next value.

func (*Decoder) UseDecodeInterfaceLoose

func (d *Decoder) UseDecodeInterfaceLoose(on bool) *Decoder

UseDecodeInterfaceLoose causes decoder to use DecodeInterfaceLoose to decode msgpack value into Go interface{}.

func (*Decoder) UseJSONTag

func (d *Decoder) UseJSONTag(on bool) *Decoder

UseJSONTag causes the Decoder to use json struct tag as fallback option if there is no msgpack tag.

type Encoder

type Encoder struct {
	// contains filtered or unexported fields
}

func NewEncoder

func NewEncoder(w io.Writer) *Encoder

NewEncoder returns a new encoder that writes to w.

func (*Encoder) Encode

func (e *Encoder) Encode(v interface{}) error

func (*Encoder) EncodeArrayLen

func (e *Encoder) EncodeArrayLen(l int) error

func (*Encoder) EncodeBool

func (e *Encoder) EncodeBool(value bool) error

func (*Encoder) EncodeBytes

func (e *Encoder) EncodeBytes(v []byte) error

func (*Encoder) EncodeBytesLen

func (e *Encoder) EncodeBytesLen(l int) error

func (*Encoder) EncodeDuration

func (e *Encoder) EncodeDuration(d time.Duration) error

func (*Encoder) EncodeExtHeader

func (e *Encoder) EncodeExtHeader(typeID int8, length int) error

func (*Encoder) EncodeFloat32

func (e *Encoder) EncodeFloat32(n float32) error

func (*Encoder) EncodeFloat64

func (e *Encoder) EncodeFloat64(n float64) error

func (*Encoder) EncodeInt

func (e *Encoder) EncodeInt(n int64) error

EncodeNumber encodes an int64 in 1, 2, 3, 5, or 9 bytes. Type of the number is lost during encoding.

func (*Encoder) EncodeInt16

func (e *Encoder) EncodeInt16(n int16) error

EncodeInt16 encodes an int16 in 3 bytes preserving type of the number.

func (*Encoder) EncodeInt32

func (e *Encoder) EncodeInt32(n int32) error

EncodeInt32 encodes an int32 in 5 bytes preserving type of the number.

func (*Encoder) EncodeInt64

func (e *Encoder) EncodeInt64(n int64) error

EncodeInt64 encodes an int64 in 9 bytes preserving type of the number.

func (*Encoder) EncodeInt8

func (e *Encoder) EncodeInt8(n int8) error

EncodeInt8 encodes an int8 in 2 bytes preserving type of the number.

func (*Encoder) EncodeMapLen

func (e *Encoder) EncodeMapLen(l int) error

func (*Encoder) EncodeMulti

func (e *Encoder) EncodeMulti(v ...interface{}) error

func (*Encoder) EncodeNil

func (e *Encoder) EncodeNil() error

func (*Encoder) EncodeString

func (e *Encoder) EncodeString(v string) error

func (*Encoder) EncodeTime

func (e *Encoder) EncodeTime(tm time.Time) error

func (*Encoder) EncodeUint

func (e *Encoder) EncodeUint(n uint64) error

EncodeUnsignedNumber encodes an uint64 in 1, 2, 3, 5, or 9 bytes. Type of the number is lost during encoding.

func (*Encoder) EncodeUint16

func (e *Encoder) EncodeUint16(n uint16) error

EncodeUint16 encodes an uint16 in 3 bytes preserving type of the number.

func (*Encoder) EncodeUint32

func (e *Encoder) EncodeUint32(n uint32) error

EncodeUint32 encodes an uint16 in 5 bytes preserving type of the number.

func (*Encoder) EncodeUint64

func (e *Encoder) EncodeUint64(n uint64) error

EncodeUint64 encodes an uint16 in 9 bytes preserving type of the number.

func (*Encoder) EncodeUint8

func (e *Encoder) EncodeUint8(n uint8) error

EncodeUint8 encodes an uint8 in 2 bytes preserving type of the number.

func (*Encoder) EncodeValue

func (e *Encoder) EncodeValue(v reflect.Value) error

func (*Encoder) Reset

func (e *Encoder) Reset(w io.Writer)

func (*Encoder) SortMapKeys

func (e *Encoder) SortMapKeys(on bool) *Encoder

SortMapKeys causes the Encoder to encode map keys in increasing order. Supported map types are:

  • map[string]string
  • map[string]interface{}

func (*Encoder) StructAsArray

func (e *Encoder) StructAsArray(on bool) *Encoder

StructAsArray causes the Encoder to encode Go structs as msgpack arrays.

func (*Encoder) UseCompactEncoding

func (e *Encoder) UseCompactEncoding(on bool) *Encoder

UseCompactEncoding causes the Encoder to chose the most compact encoding. For example, it allows to encode small Go int64 as msgpack int8 saving 7 bytes.

func (*Encoder) UseCompactFloats

func (e *Encoder) UseCompactFloats(on bool)

UseCompactFloats causes the Encoder to chose a compact integer encoding for floats that can be represented as integers.

func (*Encoder) UseJSONTag

func (e *Encoder) UseJSONTag(on bool) *Encoder

UseJSONTag causes the Encoder to use json struct tag as fallback option if there is no msgpack tag.

type Marshaler

type Marshaler interface {
	MarshalMsgpack() ([]byte, error)
}

type Unmarshaler

type Unmarshaler interface {
	UnmarshalMsgpack([]byte) error
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL