package json import ( "reflect" "sync" "github.com/bytedance/sonic" ) type Marshaler interface { MarshalJSONTo(buf []byte) []byte } var ( Unmarshal = sonic.Unmarshal Valid = sonic.Valid NewDecoder = sonic.ConfigDefault.NewDecoder ) // Marshal returns the JSON encoding of v. // // It's like json.Marshal, but with some differences: // // - It's ~4-5x faster in most cases. // // - It also supports custom Marshaler interface (MarshalJSONTo(buf []byte) []byte) // to allow further optimizations. // // - It leverages the strutils library. // // - It drops the need to implement Marshaler or json.Marshaler by supports extra field tags: // // `byte_size` to format the field to human readable size. // // `unix_time` to format the uint64 field to string date-time without specifying MarshalJSONTo. // // `use_marshaler` to force using the custom marshaler for primitive types declaration (e.g. `type Status int`). // // - It correct the behavior of *url.URL and time.Duration. // // - It does not support maps other than string-keyed maps. func Marshal(v any) ([]byte, error) { buf := newBytes() defer putBytes(buf) return cloneBytes(appendMarshal(reflect.ValueOf(v), buf)), nil } func MarshalTo(v any, buf []byte) []byte { return appendMarshal(reflect.ValueOf(v), buf) } const bufSize = 1024 var bytesPool = sync.Pool{ New: func() any { return make([]byte, 0, bufSize) }, } func newBytes() []byte { return bytesPool.Get().([]byte) } func putBytes(buf []byte) { bytesPool.Put(buf[:0]) } func cloneBytes(buf []byte) (res []byte) { return append(res, buf...) }