123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245 |
- // Copyright 2010 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- // Package json implements encoding and decoding of JSON objects as defined in
- // RFC 4627. The mapping between JSON objects and Go values is described
- // in the documentation for the Marshal and Unmarshal functions.
- //
- // See "JSON and Go" for an introduction to this package:
- // https://golang.org/doc/articles/json_and_go.html
- package json
- import (
- "bytes"
- "encoding"
- "encoding/base64"
- "math"
- "reflect"
- "runtime"
- "sort"
- "strconv"
- "strings"
- "sync"
- "unicode"
- "unicode/utf8"
- )
- // Marshal returns the JSON encoding of v.
- //
- // Marshal traverses the value v recursively.
- // If an encountered value implements the Marshaler interface
- // and is not a nil pointer, Marshal calls its MarshalJSON method
- // to produce JSON. The nil pointer exception is not strictly necessary
- // but mimics a similar, necessary exception in the behavior of
- // UnmarshalJSON.
- //
- // Otherwise, Marshal uses the following type-dependent default encodings:
- //
- // Boolean values encode as JSON booleans.
- //
- // Floating point, integer, and Number values encode as JSON numbers.
- //
- // String values encode as JSON strings coerced to valid UTF-8,
- // replacing invalid bytes with the Unicode replacement rune.
- // The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e"
- // to keep some browsers from misinterpreting JSON output as HTML.
- // Ampersand "&" is also escaped to "\u0026" for the same reason.
- //
- // Array and slice values encode as JSON arrays, except that
- // []byte encodes as a base64-encoded string, and a nil slice
- // encodes as the null JSON object.
- //
- // Struct values encode as JSON objects. Each exported struct field
- // becomes a member of the object unless
- // - the field's tag is "-", or
- // - the field is empty and its tag specifies the "omitempty" option.
- // The empty values are false, 0, any
- // nil pointer or interface value, and any array, slice, map, or string of
- // length zero. The object's default key string is the struct field name
- // but can be specified in the struct field's tag value. The "json" key in
- // the struct field's tag value is the key name, followed by an optional comma
- // and options. Examples:
- //
- // // Field is ignored by this package.
- // Field int `json:"-"`
- //
- // // Field appears in JSON as key "myName".
- // Field int `json:"myName"`
- //
- // // Field appears in JSON as key "myName" and
- // // the field is omitted from the object if its value is empty,
- // // as defined above.
- // Field int `json:"myName,omitempty"`
- //
- // // Field appears in JSON as key "Field" (the default), but
- // // the field is skipped if empty.
- // // Note the leading comma.
- // Field int `json:",omitempty"`
- //
- // The "string" option signals that a field is stored as JSON inside a
- // JSON-encoded string. It applies only to fields of string, floating point,
- // integer, or boolean types. This extra level of encoding is sometimes used
- // when communicating with JavaScript programs:
- //
- // Int64String int64 `json:",string"`
- //
- // The key name will be used if it's a non-empty string consisting of
- // only Unicode letters, digits, dollar signs, percent signs, hyphens,
- // underscores and slashes.
- //
- // Anonymous struct fields are usually marshaled as if their inner exported fields
- // were fields in the outer struct, subject to the usual Go visibility rules amended
- // as described in the next paragraph.
- // An anonymous struct field with a name given in its JSON tag is treated as
- // having that name, rather than being anonymous.
- // An anonymous struct field of interface type is treated the same as having
- // that type as its name, rather than being anonymous.
- //
- // The Go visibility rules for struct fields are amended for JSON when
- // deciding which field to marshal or unmarshal. If there are
- // multiple fields at the same level, and that level is the least
- // nested (and would therefore be the nesting level selected by the
- // usual Go rules), the following extra rules apply:
- //
- // 1) Of those fields, if any are JSON-tagged, only tagged fields are considered,
- // even if there are multiple untagged fields that would otherwise conflict.
- // 2) If there is exactly one field (tagged or not according to the first rule), that is selected.
- // 3) Otherwise there are multiple fields, and all are ignored; no error occurs.
- //
- // Handling of anonymous struct fields is new in Go 1.1.
- // Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of
- // an anonymous struct field in both current and earlier versions, give the field
- // a JSON tag of "-".
- //
- // Map values encode as JSON objects.
- // The map's key type must be string; the map keys are used as JSON object
- // keys, subject to the UTF-8 coercion described for string values above.
- //
- // Pointer values encode as the value pointed to.
- // A nil pointer encodes as the null JSON object.
- //
- // Interface values encode as the value contained in the interface.
- // A nil interface value encodes as the null JSON object.
- //
- // Channel, complex, and function values cannot be encoded in JSON.
- // Attempting to encode such a value causes Marshal to return
- // an UnsupportedTypeError.
- //
- // JSON cannot represent cyclic data structures and Marshal does not
- // handle them. Passing cyclic structures to Marshal will result in
- // an infinite recursion.
- //
- func Marshal(v interface{}) ([]byte, error) {
- return marshal(v, false)
- }
- // MarshalIndent is like Marshal but applies Indent to format the output.
- func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
- b, err := Marshal(v)
- if err != nil {
- return nil, err
- }
- var buf bytes.Buffer
- err = Indent(&buf, b, prefix, indent)
- if err != nil {
- return nil, err
- }
- return buf.Bytes(), nil
- }
- // MarshalCanonical is like Marshal but encodes into Canonical JSON.
- // Read more at: http://wiki.laptop.org/go/Canonical_JSON
- func MarshalCanonical(v interface{}) ([]byte, error) {
- return marshal(v, true)
- }
- func marshal(v interface{}, canonical bool) ([]byte, error) {
- e := &encodeState{canonical: canonical}
- err := e.marshal(v)
- if err != nil {
- return nil, err
- }
- return e.Bytes(), nil
- }
- // HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029
- // characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029
- // so that the JSON will be safe to embed inside HTML <script> tags.
- // For historical reasons, web browsers don't honor standard HTML
- // escaping within <script> tags, so an alternative JSON encoding must
- // be used.
- func HTMLEscape(dst *bytes.Buffer, src []byte) {
- // The characters can only appear in string literals,
- // so just scan the string one byte at a time.
- start := 0
- for i, c := range src {
- if c == '<' || c == '>' || c == '&' {
- if start < i {
- dst.Write(src[start:i])
- }
- dst.WriteString(`\u00`)
- dst.WriteByte(hex[c>>4])
- dst.WriteByte(hex[c&0xF])
- start = i + 1
- }
- // Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).
- if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
- if start < i {
- dst.Write(src[start:i])
- }
- dst.WriteString(`\u202`)
- dst.WriteByte(hex[src[i+2]&0xF])
- start = i + 3
- }
- }
- if start < len(src) {
- dst.Write(src[start:])
- }
- }
- // Marshaler is the interface implemented by objects that
- // can marshal themselves into valid JSON.
- type Marshaler interface {
- MarshalJSON() ([]byte, error)
- }
- // An UnsupportedTypeError is returned by Marshal when attempting
- // to encode an unsupported value type.
- type UnsupportedTypeError struct {
- Type reflect.Type
- }
- func (e *UnsupportedTypeError) Error() string {
- return "json: unsupported type: " + e.Type.String()
- }
- type UnsupportedValueError struct {
- Value reflect.Value
- Str string
- }
- func (e *UnsupportedValueError) Error() string {
- return "json: unsupported value: " + e.Str
- }
- // Before Go 1.2, an InvalidUTF8Error was returned by Marshal when
- // attempting to encode a string value with invalid UTF-8 sequences.
- // As of Go 1.2, Marshal instead coerces the string to valid UTF-8 by
- // replacing invalid bytes with the Unicode replacement rune U+FFFD.
- // This error is no longer generated but is kept for backwards compatibility
- // with programs that might mention it.
- type InvalidUTF8Error struct {
- S string // the whole string value that caused the error
- }
- func (e *InvalidUTF8Error) Error() string {
- return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
- }
- type MarshalerError struct {
- Type reflect.Type
- Err error
- }
- func (e *MarshalerError) Error() string {
- return "json: error calling MarshalJSON for type " + e.Type.String() + ": " + e.Err.Error()
- }
- var hex = "0123456789abcdef"
- // An encodeState encodes JSON into a bytes.Buffer.
- type encodeState struct {
- bytes.Buffer // accumulated output
- scratch [64]byte
- canonical bool
- }
- var encodeStatePool sync.Pool
- func newEncodeState(canonical bool) *encodeState {
- if v := encodeStatePool.Get(); v != nil {
- e := v.(*encodeState)
- e.Reset()
- e.canonical = canonical
- return e
- }
- return &encodeState{canonical: canonical}
- }
- func (e *encodeState) marshal(v interface{}) (err error) {
- defer func() {
- if r := recover(); r != nil {
- if _, ok := r.(runtime.Error); ok {
- panic(r)
- }
- if s, ok := r.(string); ok {
- panic(s)
- }
- err = r.(error)
- }
- }()
- e.reflectValue(reflect.ValueOf(v))
- return nil
- }
- func (e *encodeState) error(err error) {
- panic(err)
- }
- func isEmptyValue(v reflect.Value) bool {
- switch v.Kind() {
- case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
- return v.Len() == 0
- case reflect.Bool:
- return !v.Bool()
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- return v.Int() == 0
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- return v.Uint() == 0
- case reflect.Float32, reflect.Float64:
- return v.Float() == 0
- case reflect.Interface, reflect.Ptr:
- return v.IsNil()
- }
- return false
- }
- func (e *encodeState) reflectValue(v reflect.Value) {
- e.valueEncoder(v)(e, v, false)
- }
- type encoderFunc func(e *encodeState, v reflect.Value, quoted bool)
- var encoderCache struct {
- sync.RWMutex
- m map[reflect.Type]encoderFunc
- }
- func (e *encodeState) valueEncoder(v reflect.Value) encoderFunc {
- if !v.IsValid() {
- return invalidValueEncoder
- }
- return e.typeEncoder(v.Type())
- }
- func (e *encodeState) typeEncoder(t reflect.Type) encoderFunc {
- encoderCache.RLock()
- f := encoderCache.m[t]
- encoderCache.RUnlock()
- if f != nil {
- return f
- }
- // To deal with recursive types, populate the map with an
- // indirect func before we build it. This type waits on the
- // real func (f) to be ready and then calls it. This indirect
- // func is only used for recursive types.
- encoderCache.Lock()
- if encoderCache.m == nil {
- encoderCache.m = make(map[reflect.Type]encoderFunc)
- }
- var wg sync.WaitGroup
- wg.Add(1)
- encoderCache.m[t] = func(e *encodeState, v reflect.Value, quoted bool) {
- wg.Wait()
- f(e, v, quoted)
- }
- encoderCache.Unlock()
- // Compute fields without lock.
- // Might duplicate effort but won't hold other computations back.
- f = e.newTypeEncoder(t, true)
- wg.Done()
- encoderCache.Lock()
- encoderCache.m[t] = f
- encoderCache.Unlock()
- return f
- }
- var (
- marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
- textMarshalerType = reflect.TypeOf(new(encoding.TextMarshaler)).Elem()
- )
- // newTypeEncoder constructs an encoderFunc for a type.
- // The returned encoder only checks CanAddr when allowAddr is true.
- func (e *encodeState) newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
- if t.Implements(marshalerType) {
- return marshalerEncoder
- }
- if t.Kind() != reflect.Ptr && allowAddr {
- if reflect.PtrTo(t).Implements(marshalerType) {
- return newCondAddrEncoder(addrMarshalerEncoder, e.newTypeEncoder(t, false))
- }
- }
- if t.Implements(textMarshalerType) {
- return textMarshalerEncoder
- }
- if t.Kind() != reflect.Ptr && allowAddr {
- if reflect.PtrTo(t).Implements(textMarshalerType) {
- return newCondAddrEncoder(addrTextMarshalerEncoder, e.newTypeEncoder(t, false))
- }
- }
- switch t.Kind() {
- case reflect.Bool:
- return boolEncoder
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- return intEncoder
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- return uintEncoder
- case reflect.Float32:
- return float32Encoder
- case reflect.Float64:
- return float64Encoder
- case reflect.String:
- return stringEncoder
- case reflect.Interface:
- return interfaceEncoder
- case reflect.Struct:
- return e.newStructEncoder(t)
- case reflect.Map:
- return e.newMapEncoder(t)
- case reflect.Slice:
- return e.newSliceEncoder(t)
- case reflect.Array:
- return e.newArrayEncoder(t)
- case reflect.Ptr:
- return e.newPtrEncoder(t)
- default:
- return unsupportedTypeEncoder
- }
- }
- func invalidValueEncoder(e *encodeState, v reflect.Value, quoted bool) {
- e.WriteString("null")
- }
- func marshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
- if v.Kind() == reflect.Ptr && v.IsNil() {
- e.WriteString("null")
- return
- }
- m := v.Interface().(Marshaler)
- b, err := m.MarshalJSON()
- if err == nil {
- // copy JSON into buffer, checking validity.
- err = compact(&e.Buffer, b, true)
- }
- if err != nil {
- e.error(&MarshalerError{v.Type(), err})
- }
- }
- func addrMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
- va := v.Addr()
- if va.IsNil() {
- e.WriteString("null")
- return
- }
- m := va.Interface().(Marshaler)
- b, err := m.MarshalJSON()
- if err == nil {
- // copy JSON into buffer, checking validity.
- err = compact(&e.Buffer, b, true)
- }
- if err != nil {
- e.error(&MarshalerError{v.Type(), err})
- }
- }
- func textMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
- if v.Kind() == reflect.Ptr && v.IsNil() {
- e.WriteString("null")
- return
- }
- m := v.Interface().(encoding.TextMarshaler)
- b, err := m.MarshalText()
- if err == nil {
- _, err = e.stringBytes(b)
- }
- if err != nil {
- e.error(&MarshalerError{v.Type(), err})
- }
- }
- func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
- va := v.Addr()
- if va.IsNil() {
- e.WriteString("null")
- return
- }
- m := va.Interface().(encoding.TextMarshaler)
- b, err := m.MarshalText()
- if err == nil {
- _, err = e.stringBytes(b)
- }
- if err != nil {
- e.error(&MarshalerError{v.Type(), err})
- }
- }
- func boolEncoder(e *encodeState, v reflect.Value, quoted bool) {
- if quoted {
- e.WriteByte('"')
- }
- if v.Bool() {
- e.WriteString("true")
- } else {
- e.WriteString("false")
- }
- if quoted {
- e.WriteByte('"')
- }
- }
- func intEncoder(e *encodeState, v reflect.Value, quoted bool) {
- b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
- if quoted {
- e.WriteByte('"')
- }
- e.Write(b)
- if quoted {
- e.WriteByte('"')
- }
- }
- func uintEncoder(e *encodeState, v reflect.Value, quoted bool) {
- b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10)
- if quoted {
- e.WriteByte('"')
- }
- e.Write(b)
- if quoted {
- e.WriteByte('"')
- }
- }
- type floatEncoder int // number of bits
- func (bits floatEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
- f := v.Float()
- if math.IsInf(f, 0) || math.IsNaN(f) || (e.canonical && math.Floor(f) != f) {
- e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, int(bits))})
- }
- var b []byte
- if e.canonical {
- b = strconv.AppendInt(e.scratch[:0], int64(f), 10)
- } else {
- b = strconv.AppendFloat(e.scratch[:0], f, 'g', -1, int(bits))
- }
- if quoted {
- e.WriteByte('"')
- }
- e.Write(b)
- if quoted {
- e.WriteByte('"')
- }
- }
- var (
- float32Encoder = (floatEncoder(32)).encode
- float64Encoder = (floatEncoder(64)).encode
- )
- func stringEncoder(e *encodeState, v reflect.Value, quoted bool) {
- if v.Type() == numberType {
- numStr := v.String()
- if numStr == "" {
- numStr = "0" // Number's zero-val
- }
- e.WriteString(numStr)
- return
- }
- if quoted {
- sb, err := Marshal(v.String())
- if err != nil {
- e.error(err)
- }
- e.string(string(sb))
- } else {
- e.string(v.String())
- }
- }
- func interfaceEncoder(e *encodeState, v reflect.Value, quoted bool) {
- if v.IsNil() {
- e.WriteString("null")
- return
- }
- e.reflectValue(v.Elem())
- }
- func unsupportedTypeEncoder(e *encodeState, v reflect.Value, quoted bool) {
- e.error(&UnsupportedTypeError{v.Type()})
- }
- type structEncoder struct {
- fields []field
- fieldEncs []encoderFunc
- }
- func (se *structEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
- e.WriteByte('{')
- first := true
- for i, f := range se.fields {
- fv := fieldByIndex(v, f.index)
- if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) {
- continue
- }
- if first {
- first = false
- } else {
- e.WriteByte(',')
- }
- e.string(f.name)
- e.WriteByte(':')
- se.fieldEncs[i](e, fv, f.quoted)
- }
- e.WriteByte('}')
- }
- func (e *encodeState) newStructEncoder(t reflect.Type) encoderFunc {
- fields := cachedTypeFields(t, e.canonical)
- se := &structEncoder{
- fields: fields,
- fieldEncs: make([]encoderFunc, len(fields)),
- }
- for i, f := range fields {
- se.fieldEncs[i] = e.typeEncoder(typeByIndex(t, f.index))
- }
- return se.encode
- }
- type mapEncoder struct {
- elemEnc encoderFunc
- }
- func (me *mapEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
- if v.IsNil() {
- e.WriteString("null")
- return
- }
- e.WriteByte('{')
- var sv stringValues = v.MapKeys()
- sort.Sort(sv)
- for i, k := range sv {
- if i > 0 {
- e.WriteByte(',')
- }
- e.string(k.String())
- e.WriteByte(':')
- me.elemEnc(e, v.MapIndex(k), false)
- }
- e.WriteByte('}')
- }
- func (e *encodeState) newMapEncoder(t reflect.Type) encoderFunc {
- if t.Key().Kind() != reflect.String {
- return unsupportedTypeEncoder
- }
- me := &mapEncoder{e.typeEncoder(t.Elem())}
- return me.encode
- }
- func encodeByteSlice(e *encodeState, v reflect.Value, _ bool) {
- if v.IsNil() {
- e.WriteString("null")
- return
- }
- s := v.Bytes()
- e.WriteByte('"')
- if len(s) < 1024 {
- // for small buffers, using Encode directly is much faster.
- dst := make([]byte, base64.StdEncoding.EncodedLen(len(s)))
- base64.StdEncoding.Encode(dst, s)
- e.Write(dst)
- } else {
- // for large buffers, avoid unnecessary extra temporary
- // buffer space.
- enc := base64.NewEncoder(base64.StdEncoding, e)
- enc.Write(s)
- enc.Close()
- }
- e.WriteByte('"')
- }
- // sliceEncoder just wraps an arrayEncoder, checking to make sure the value isn't nil.
- type sliceEncoder struct {
- arrayEnc encoderFunc
- }
- func (se *sliceEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
- if v.IsNil() {
- e.WriteString("null")
- return
- }
- se.arrayEnc(e, v, false)
- }
- func (e *encodeState) newSliceEncoder(t reflect.Type) encoderFunc {
- // Byte slices get special treatment; arrays don't.
- if t.Elem().Kind() == reflect.Uint8 {
- return encodeByteSlice
- }
- enc := &sliceEncoder{e.newArrayEncoder(t)}
- return enc.encode
- }
- type arrayEncoder struct {
- elemEnc encoderFunc
- }
- func (ae *arrayEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
- e.WriteByte('[')
- n := v.Len()
- for i := 0; i < n; i++ {
- if i > 0 {
- e.WriteByte(',')
- }
- ae.elemEnc(e, v.Index(i), false)
- }
- e.WriteByte(']')
- }
- func (e *encodeState) newArrayEncoder(t reflect.Type) encoderFunc {
- enc := &arrayEncoder{e.typeEncoder(t.Elem())}
- return enc.encode
- }
- type ptrEncoder struct {
- elemEnc encoderFunc
- }
- func (pe *ptrEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
- if v.IsNil() {
- e.WriteString("null")
- return
- }
- pe.elemEnc(e, v.Elem(), quoted)
- }
- func (e *encodeState) newPtrEncoder(t reflect.Type) encoderFunc {
- enc := &ptrEncoder{e.typeEncoder(t.Elem())}
- return enc.encode
- }
- type condAddrEncoder struct {
- canAddrEnc, elseEnc encoderFunc
- }
- func (ce *condAddrEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
- if v.CanAddr() {
- ce.canAddrEnc(e, v, quoted)
- } else {
- ce.elseEnc(e, v, quoted)
- }
- }
- // newCondAddrEncoder returns an encoder that checks whether its value
- // CanAddr and delegates to canAddrEnc if so, else to elseEnc.
- func newCondAddrEncoder(canAddrEnc, elseEnc encoderFunc) encoderFunc {
- enc := &condAddrEncoder{canAddrEnc: canAddrEnc, elseEnc: elseEnc}
- return enc.encode
- }
- func isValidTag(s string) bool {
- if s == "" {
- return false
- }
- for _, c := range s {
- switch {
- case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
- // Backslash and quote chars are reserved, but
- // otherwise any punctuation chars are allowed
- // in a tag name.
- default:
- if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
- return false
- }
- }
- }
- return true
- }
- func fieldByIndex(v reflect.Value, index []int) reflect.Value {
- for _, i := range index {
- if v.Kind() == reflect.Ptr {
- if v.IsNil() {
- return reflect.Value{}
- }
- v = v.Elem()
- }
- v = v.Field(i)
- }
- return v
- }
- func typeByIndex(t reflect.Type, index []int) reflect.Type {
- for _, i := range index {
- if t.Kind() == reflect.Ptr {
- t = t.Elem()
- }
- t = t.Field(i).Type
- }
- return t
- }
- // stringValues is a slice of reflect.Value holding *reflect.StringValue.
- // It implements the methods to sort by string.
- type stringValues []reflect.Value
- func (sv stringValues) Len() int { return len(sv) }
- func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
- func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
- func (sv stringValues) get(i int) string { return sv[i].String() }
- // NOTE: keep in sync with stringBytes below.
- func (e *encodeState) string(s string) (int, error) {
- len0 := e.Len()
- e.WriteByte('"')
- start := 0
- for i := 0; i < len(s); {
- if b := s[i]; b < utf8.RuneSelf {
- if b != '\\' && b != '"' {
- if e.canonical || (0x20 <= b && b != '<' && b != '>' && b != '&') {
- i++
- continue
- }
- }
- if start < i {
- e.WriteString(s[start:i])
- }
- switch b {
- case '\\', '"':
- e.WriteByte('\\')
- e.WriteByte(b)
- case '\n':
- e.WriteByte('\\')
- e.WriteByte('n')
- case '\r':
- e.WriteByte('\\')
- e.WriteByte('r')
- case '\t':
- e.WriteByte('\\')
- e.WriteByte('t')
- default:
- // This encodes bytes < 0x20 except for \n and \r,
- // as well as <, > and &. The latter are escaped because they
- // can lead to security holes when user-controlled strings
- // are rendered into JSON and served to some browsers.
- e.WriteString(`\u00`)
- e.WriteByte(hex[b>>4])
- e.WriteByte(hex[b&0xF])
- }
- i++
- start = i
- continue
- }
- if e.canonical {
- i++
- continue
- }
- c, size := utf8.DecodeRuneInString(s[i:])
- if c == utf8.RuneError && size == 1 {
- if start < i {
- e.WriteString(s[start:i])
- }
- e.WriteString(`\ufffd`)
- i += size
- start = i
- continue
- }
- // U+2028 is LINE SEPARATOR.
- // U+2029 is PARAGRAPH SEPARATOR.
- // They are both technically valid characters in JSON strings,
- // but don't work in JSONP, which has to be evaluated as JavaScript,
- // and can lead to security holes there. It is valid JSON to
- // escape them, so we do so unconditionally.
- // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
- if c == '\u2028' || c == '\u2029' {
- if start < i {
- e.WriteString(s[start:i])
- }
- e.WriteString(`\u202`)
- e.WriteByte(hex[c&0xF])
- i += size
- start = i
- continue
- }
- i += size
- }
- if start < len(s) {
- e.WriteString(s[start:])
- }
- e.WriteByte('"')
- return e.Len() - len0, nil
- }
- // NOTE: keep in sync with string above.
- func (e *encodeState) stringBytes(s []byte) (int, error) {
- len0 := e.Len()
- e.WriteByte('"')
- start := 0
- for i := 0; i < len(s); {
- if b := s[i]; b < utf8.RuneSelf {
- if b != '\\' && b != '"' {
- if e.canonical || (0x20 <= b && b != '<' && b != '>' && b != '&') {
- i++
- continue
- }
- }
- if start < i {
- e.Write(s[start:i])
- }
- switch b {
- case '\\', '"':
- e.WriteByte('\\')
- e.WriteByte(b)
- case '\n':
- e.WriteByte('\\')
- e.WriteByte('n')
- case '\r':
- e.WriteByte('\\')
- e.WriteByte('r')
- case '\t':
- e.WriteByte('\\')
- e.WriteByte('t')
- default:
- // This encodes bytes < 0x20 except for \n and \r,
- // as well as <, >, and &. The latter are escaped because they
- // can lead to security holes when user-controlled strings
- // are rendered into JSON and served to some browsers.
- e.WriteString(`\u00`)
- e.WriteByte(hex[b>>4])
- e.WriteByte(hex[b&0xF])
- }
- i++
- start = i
- continue
- }
- if e.canonical {
- i++
- continue
- }
- c, size := utf8.DecodeRune(s[i:])
- if c == utf8.RuneError && size == 1 {
- if start < i {
- e.Write(s[start:i])
- }
- e.WriteString(`\ufffd`)
- i += size
- start = i
- continue
- }
- // U+2028 is LINE SEPARATOR.
- // U+2029 is PARAGRAPH SEPARATOR.
- // They are both technically valid characters in JSON strings,
- // but don't work in JSONP, which has to be evaluated as JavaScript,
- // and can lead to security holes there. It is valid JSON to
- // escape them, so we do so unconditionally.
- // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
- if c == '\u2028' || c == '\u2029' {
- if start < i {
- e.Write(s[start:i])
- }
- e.WriteString(`\u202`)
- e.WriteByte(hex[c&0xF])
- i += size
- start = i
- continue
- }
- i += size
- }
- if start < len(s) {
- e.Write(s[start:])
- }
- e.WriteByte('"')
- return e.Len() - len0, nil
- }
- // A field represents a single field found in a struct.
- type field struct {
- name string
- nameBytes []byte // []byte(name)
- equalFold func(s, t []byte) bool // bytes.EqualFold or equivalent
- tag bool
- index []int
- typ reflect.Type
- omitEmpty bool
- quoted bool
- }
- func fillField(f field) field {
- f.nameBytes = []byte(f.name)
- f.equalFold = foldFunc(f.nameBytes)
- return f
- }
- // byName sorts field by name, breaking ties with depth,
- // then breaking ties with "name came from json tag", then
- // breaking ties with index sequence.
- type byName []field
- func (x byName) Len() int { return len(x) }
- func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
- func (x byName) Less(i, j int) bool {
- if x[i].name != x[j].name {
- return x[i].name < x[j].name
- }
- if len(x[i].index) != len(x[j].index) {
- return len(x[i].index) < len(x[j].index)
- }
- if x[i].tag != x[j].tag {
- return x[i].tag
- }
- return byIndex(x).Less(i, j)
- }
- // byIndex sorts field by index sequence.
- type byIndex []field
- func (x byIndex) Len() int { return len(x) }
- func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
- func (x byIndex) Less(i, j int) bool {
- for k, xik := range x[i].index {
- if k >= len(x[j].index) {
- return false
- }
- if xik != x[j].index[k] {
- return xik < x[j].index[k]
- }
- }
- return len(x[i].index) < len(x[j].index)
- }
- // typeFields returns a list of fields that JSON should recognize for the given type.
- // The algorithm is breadth-first search over the set of structs to include - the top struct
- // and then any reachable anonymous structs.
- func typeFields(t reflect.Type) []field {
- // Anonymous fields to explore at the current level and the next.
- current := []field{}
- next := []field{{typ: t}}
- // Count of queued names for current level and the next.
- count := map[reflect.Type]int{}
- nextCount := map[reflect.Type]int{}
- // Types already visited at an earlier level.
- visited := map[reflect.Type]bool{}
- // Fields found.
- var fields []field
- for len(next) > 0 {
- current, next = next, current[:0]
- count, nextCount = nextCount, map[reflect.Type]int{}
- for _, f := range current {
- if visited[f.typ] {
- continue
- }
- visited[f.typ] = true
- // Scan f.typ for fields to include.
- for i := 0; i < f.typ.NumField(); i++ {
- sf := f.typ.Field(i)
- if sf.PkgPath != "" { // unexported
- continue
- }
- tag := sf.Tag.Get("json")
- if tag == "-" {
- continue
- }
- name, opts := parseTag(tag)
- if !isValidTag(name) {
- name = ""
- }
- index := make([]int, len(f.index)+1)
- copy(index, f.index)
- index[len(f.index)] = i
- ft := sf.Type
- if ft.Name() == "" && ft.Kind() == reflect.Ptr {
- // Follow pointer.
- ft = ft.Elem()
- }
- // Only strings, floats, integers, and booleans can be quoted.
- quoted := false
- if opts.Contains("string") {
- switch ft.Kind() {
- case reflect.Bool,
- reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
- reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
- reflect.Float32, reflect.Float64,
- reflect.String:
- quoted = true
- }
- }
- // Record found field and index sequence.
- if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
- tagged := name != ""
- if name == "" {
- name = sf.Name
- }
- fields = append(fields, fillField(field{
- name: name,
- tag: tagged,
- index: index,
- typ: ft,
- omitEmpty: opts.Contains("omitempty"),
- quoted: quoted,
- }))
- if count[f.typ] > 1 {
- // If there were multiple instances, add a second,
- // so that the annihilation code will see a duplicate.
- // It only cares about the distinction between 1 or 2,
- // so don't bother generating any more copies.
- fields = append(fields, fields[len(fields)-1])
- }
- continue
- }
- // Record new anonymous struct to explore in next round.
- nextCount[ft]++
- if nextCount[ft] == 1 {
- next = append(next, fillField(field{name: ft.Name(), index: index, typ: ft}))
- }
- }
- }
- }
- sort.Sort(byName(fields))
- // Delete all fields that are hidden by the Go rules for embedded fields,
- // except that fields with JSON tags are promoted.
- // The fields are sorted in primary order of name, secondary order
- // of field index length. Loop over names; for each name, delete
- // hidden fields by choosing the one dominant field that survives.
- out := fields[:0]
- for advance, i := 0, 0; i < len(fields); i += advance {
- // One iteration per name.
- // Find the sequence of fields with the name of this first field.
- fi := fields[i]
- name := fi.name
- for advance = 1; i+advance < len(fields); advance++ {
- fj := fields[i+advance]
- if fj.name != name {
- break
- }
- }
- if advance == 1 { // Only one field with this name
- out = append(out, fi)
- continue
- }
- dominant, ok := dominantField(fields[i : i+advance])
- if ok {
- out = append(out, dominant)
- }
- }
- return out
- }
- // dominantField looks through the fields, all of which are known to
- // have the same name, to find the single field that dominates the
- // others using Go's embedding rules, modified by the presence of
- // JSON tags. If there are multiple top-level fields, the boolean
- // will be false: This condition is an error in Go and we skip all
- // the fields.
- func dominantField(fields []field) (field, bool) {
- // The fields are sorted in increasing index-length order. The winner
- // must therefore be one with the shortest index length. Drop all
- // longer entries, which is easy: just truncate the slice.
- length := len(fields[0].index)
- tagged := -1 // Index of first tagged field.
- for i, f := range fields {
- if len(f.index) > length {
- fields = fields[:i]
- break
- }
- if f.tag {
- if tagged >= 0 {
- // Multiple tagged fields at the same level: conflict.
- // Return no field.
- return field{}, false
- }
- tagged = i
- }
- }
- if tagged >= 0 {
- return fields[tagged], true
- }
- // All remaining fields have the same length. If there's more than one,
- // we have a conflict (two fields named "X" at the same level) and we
- // return no field.
- if len(fields) > 1 {
- return field{}, false
- }
- return fields[0], true
- }
- type fields struct {
- byName []field
- byIndex []field
- }
- var fieldCache struct {
- sync.RWMutex
- m map[reflect.Type]*fields
- }
- // cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
- func cachedTypeFields(t reflect.Type, canonical bool) []field {
- fieldCache.RLock()
- x := fieldCache.m[t]
- fieldCache.RUnlock()
- var f []field
- if x != nil {
- if canonical {
- f = x.byName
- }
- f = x.byIndex
- }
- if f != nil {
- return f
- }
- // Compute fields without lock.
- // Might duplicate effort but won't hold other computations back.
- f = typeFields(t)
- if f == nil {
- f = []field{}
- }
- if !canonical {
- sort.Sort(byIndex(f))
- }
- fieldCache.Lock()
- if fieldCache.m == nil {
- fieldCache.m = map[reflect.Type]*fields{}
- }
- x = fieldCache.m[t]
- fieldCache.Unlock()
- if x == nil {
- x = new(fields)
- }
- if canonical {
- x.byName = f
- } else {
- x.byIndex = f
- }
- return f
- }
|