// 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 as defined in // RFC 7159. The mapping between JSON 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 ( ) // 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. If no MarshalJSON method is present but the // value implements encoding.TextMarshaler instead, Marshal calls // its MarshalText method and encodes the result as a JSON string. // 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. // So that the JSON will be safe to embed inside HTML <script> tags, // the string is encoded using HTMLEscape, // which replaces "<", ">", "&", U+2028, and U+2029 are escaped // to "\u003c","\u003e", "\u0026", "\u2028", and "\u2029". // This replacement can be disabled when using an Encoder, // by calling SetEscapeHTML(false). // // 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 value. // // Struct values encode as JSON objects. // Each exported struct field becomes a member of the object, using the // field name as the object key, unless the field is omitted for one of the // reasons given below. // // The encoding of each struct field can be customized by the format string // stored under the "json" key in the struct field's tag. // The format string gives the name of the field, possibly followed by a // comma-separated list of options. The name may be empty in order to // specify options without overriding the default field name. // // The "omitempty" option specifies that the field should be omitted // from the encoding if the field has an empty value, defined as // false, 0, a nil pointer, a nil interface value, and any empty array, // slice, map, or string. // // As a special case, if the field tag is "-", the field is always omitted. // Note that a field with name "-" can still be generated using the tag "-,". // // Examples of struct field tags and their meanings: // // // 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"` // // // Field is ignored by this package. // Field int `json:"-"` // // // Field appears in JSON as key "-". // Field int `json:"-,"` // // 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, and ASCII punctuation except quotation // marks, backslash, and comma. // // 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 either be a // string, an integer type, or implement encoding.TextMarshaler. The map keys // are sorted and used as JSON object keys by applying the following rules, // subject to the UTF-8 coercion described for string values above: // - keys of any string type are used directly // - encoding.TextMarshalers are marshaled // - integer keys are converted to strings // // Pointer values encode as the value pointed to. // A nil pointer encodes as the null JSON value. // // Interface values encode as the value contained in the interface. // A nil interface value encodes as the null JSON value. // // 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 error. // func ( interface{}) ([]byte, error) { := newEncodeState() := .marshal(, encOpts{escapeHTML: true}) if != nil { return nil, } := append([]byte(nil), .Bytes()...) encodeStatePool.Put() return , nil } // MarshalIndent is like Marshal but applies Indent to format the output. // Each JSON element in the output will begin on a new line beginning with prefix // followed by one or more copies of indent according to the indentation nesting. func ( interface{}, , string) ([]byte, error) { , := Marshal() if != nil { return nil, } var bytes.Buffer = Indent(&, , , ) if != nil { return nil, } return .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 ( *bytes.Buffer, []byte) { // The characters can only appear in string literals, // so just scan the string one byte at a time. := 0 for , := range { if == '<' || == '>' || == '&' { if < { .Write([:]) } .WriteString(`\u00`) .WriteByte(hex[>>4]) .WriteByte(hex[&0xF]) = + 1 } // Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9). if == 0xE2 && +2 < len() && [+1] == 0x80 && [+2]&^1 == 0xA8 { if < { .Write([:]) } .WriteString(`\u202`) .WriteByte(hex[[+2]&0xF]) = + 3 } } if < len() { .Write([:]) } } // Marshaler is the interface implemented by types 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 ( *UnsupportedTypeError) () string { return "json: unsupported type: " + .Type.String() } // An UnsupportedValueError is returned by Marshal when attempting // to encode an unsupported value. type UnsupportedValueError struct { Value reflect.Value Str string } func ( *UnsupportedValueError) () string { return "json: unsupported value: " + .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. // // Deprecated: No longer used; kept for compatibility. type InvalidUTF8Error struct { S string // the whole string value that caused the error } func ( *InvalidUTF8Error) () string { return "json: invalid UTF-8 in string: " + strconv.Quote(.S) } // A MarshalerError represents an error from calling a MarshalJSON or MarshalText method. type MarshalerError struct { Type reflect.Type Err error sourceFunc string } func ( *MarshalerError) () string { := .sourceFunc if == "" { = "MarshalJSON" } return "json: error calling " + + " for type " + .Type.String() + ": " + .Err.Error() } // Unwrap returns the underlying error. func ( *MarshalerError) () error { return .Err } var hex = "0123456789abcdef" // An encodeState encodes JSON into a bytes.Buffer. type encodeState struct { bytes.Buffer // accumulated output scratch [64]byte // Keep track of what pointers we've seen in the current recursive call // path, to avoid cycles that could lead to a stack overflow. Only do // the relatively expensive map operations if ptrLevel is larger than // startDetectingCyclesAfter, so that we skip the work if we're within a // reasonable amount of nested pointers deep. ptrLevel uint ptrSeen map[interface{}]struct{} } const startDetectingCyclesAfter = 1000 var encodeStatePool sync.Pool func newEncodeState() *encodeState { if := encodeStatePool.Get(); != nil { := .(*encodeState) .Reset() if len(.ptrSeen) > 0 { panic("ptrEncoder.encode should have emptied ptrSeen via defers") } .ptrLevel = 0 return } return &encodeState{ptrSeen: make(map[interface{}]struct{})} } // jsonError is an error wrapper type for internal use only. // Panics with errors are wrapped in jsonError so that the top-level recover // can distinguish intentional panics from this package. type jsonError struct{ error } func ( *encodeState) ( interface{}, encOpts) ( error) { defer func() { if := recover(); != nil { if , := .(jsonError); { = .error } else { panic() } } }() .reflectValue(reflect.ValueOf(), ) return nil } // error aborts the encoding by panicking with err wrapped in jsonError. func ( *encodeState) ( error) { panic(jsonError{}) } func isEmptyValue( reflect.Value) bool { switch .Kind() { case reflect.Array, reflect.Map, reflect.Slice, reflect.String: return .Len() == 0 case reflect.Bool: return !.Bool() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return .Int() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return .Uint() == 0 case reflect.Float32, reflect.Float64: return .Float() == 0 case reflect.Interface, reflect.Ptr: return .IsNil() } return false } func ( *encodeState) ( reflect.Value, encOpts) { valueEncoder()(, , ) } type encOpts struct { // quoted causes primitive fields to be encoded inside JSON strings. quoted bool // escapeHTML causes '<', '>', and '&' to be escaped in JSON strings. escapeHTML bool } type encoderFunc func(e *encodeState, v reflect.Value, opts encOpts) var encoderCache sync.Map // map[reflect.Type]encoderFunc func valueEncoder( reflect.Value) encoderFunc { if !.IsValid() { return invalidValueEncoder } return typeEncoder(.Type()) } func typeEncoder( reflect.Type) encoderFunc { if , := encoderCache.Load(); { return .(encoderFunc) } // 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. var ( sync.WaitGroup encoderFunc ) .Add(1) , := encoderCache.LoadOrStore(, encoderFunc(func( *encodeState, reflect.Value, encOpts) { .Wait() (, , ) })) if { return .(encoderFunc) } // Compute the real encoder and replace the indirect func with it. = newTypeEncoder(, true) .Done() encoderCache.Store(, ) return } var ( marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() ) // newTypeEncoder constructs an encoderFunc for a type. // The returned encoder only checks CanAddr when allowAddr is true. func newTypeEncoder( reflect.Type, bool) encoderFunc { // If we have a non-pointer value whose type implements // Marshaler with a value receiver, then we're better off taking // the address of the value - otherwise we end up with an // allocation as we cast the value to an interface. if .Kind() != reflect.Ptr && && reflect.PtrTo().Implements(marshalerType) { return newCondAddrEncoder(addrMarshalerEncoder, (, false)) } if .Implements(marshalerType) { return marshalerEncoder } if .Kind() != reflect.Ptr && && reflect.PtrTo().Implements(textMarshalerType) { return newCondAddrEncoder(addrTextMarshalerEncoder, (, false)) } if .Implements(textMarshalerType) { return textMarshalerEncoder } switch .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 newStructEncoder() case reflect.Map: return newMapEncoder() case reflect.Slice: return newSliceEncoder() case reflect.Array: return newArrayEncoder() case reflect.Ptr: return newPtrEncoder() default: return unsupportedTypeEncoder } } func invalidValueEncoder( *encodeState, reflect.Value, encOpts) { .WriteString("null") } func marshalerEncoder( *encodeState, reflect.Value, encOpts) { if .Kind() == reflect.Ptr && .IsNil() { .WriteString("null") return } , := .Interface().(Marshaler) if ! { .WriteString("null") return } , := .MarshalJSON() if == nil { // copy JSON into buffer, checking validity. = compact(&.Buffer, , .escapeHTML) } if != nil { .error(&MarshalerError{.Type(), , "MarshalJSON"}) } } func addrMarshalerEncoder( *encodeState, reflect.Value, encOpts) { := .Addr() if .IsNil() { .WriteString("null") return } := .Interface().(Marshaler) , := .MarshalJSON() if == nil { // copy JSON into buffer, checking validity. = compact(&.Buffer, , .escapeHTML) } if != nil { .error(&MarshalerError{.Type(), , "MarshalJSON"}) } } func textMarshalerEncoder( *encodeState, reflect.Value, encOpts) { if .Kind() == reflect.Ptr && .IsNil() { .WriteString("null") return } , := .Interface().(encoding.TextMarshaler) if ! { .WriteString("null") return } , := .MarshalText() if != nil { .error(&MarshalerError{.Type(), , "MarshalText"}) } .stringBytes(, .escapeHTML) } func addrTextMarshalerEncoder( *encodeState, reflect.Value, encOpts) { := .Addr() if .IsNil() { .WriteString("null") return } := .Interface().(encoding.TextMarshaler) , := .MarshalText() if != nil { .error(&MarshalerError{.Type(), , "MarshalText"}) } .stringBytes(, .escapeHTML) } func boolEncoder( *encodeState, reflect.Value, encOpts) { if .quoted { .WriteByte('"') } if .Bool() { .WriteString("true") } else { .WriteString("false") } if .quoted { .WriteByte('"') } } func intEncoder( *encodeState, reflect.Value, encOpts) { := strconv.AppendInt(.scratch[:0], .Int(), 10) if .quoted { .WriteByte('"') } .Write() if .quoted { .WriteByte('"') } } func uintEncoder( *encodeState, reflect.Value, encOpts) { := strconv.AppendUint(.scratch[:0], .Uint(), 10) if .quoted { .WriteByte('"') } .Write() if .quoted { .WriteByte('"') } } type floatEncoder int // number of bits func ( floatEncoder) ( *encodeState, reflect.Value, encOpts) { := .Float() if math.IsInf(, 0) || math.IsNaN() { .error(&UnsupportedValueError{, strconv.FormatFloat(, 'g', -1, int())}) } // Convert as if by ES6 number to string conversion. // This matches most other JSON generators. // See golang.org/issue/6384 and golang.org/issue/14135. // Like fmt %g, but the exponent cutoffs are different // and exponents themselves are not padded to two digits. := .scratch[:0] := math.Abs() := byte('f') // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. if != 0 { if == 64 && ( < 1e-6 || >= 1e21) || == 32 && (float32() < 1e-6 || float32() >= 1e21) { = 'e' } } = strconv.AppendFloat(, , , -1, int()) if == 'e' { // clean up e-09 to e-9 := len() if >= 4 && [-4] == 'e' && [-3] == '-' && [-2] == '0' { [-2] = [-1] = [:-1] } } if .quoted { .WriteByte('"') } .Write() if .quoted { .WriteByte('"') } } var ( float32Encoder = (floatEncoder(32)).encode float64Encoder = (floatEncoder(64)).encode ) func stringEncoder( *encodeState, reflect.Value, encOpts) { if .Type() == numberType { := .String() // In Go1.5 the empty string encodes to "0", while this is not a valid number literal // we keep compatibility so check validity after this. if == "" { = "0" // Number's zero-val } if !isValidNumber() { .error(fmt.Errorf("json: invalid number literal %q", )) } if .quoted { .WriteByte('"') } .WriteString() if .quoted { .WriteByte('"') } return } if .quoted { := newEncodeState() // Since we encode the string twice, we only need to escape HTML // the first time. .string(.String(), .escapeHTML) .stringBytes(.Bytes(), false) encodeStatePool.Put() } else { .string(.String(), .escapeHTML) } } // isValidNumber reports whether s is a valid JSON number literal. func isValidNumber( string) bool { // This function implements the JSON numbers grammar. // See https://tools.ietf.org/html/rfc7159#section-6 // and https://www.json.org/img/number.png if == "" { return false } // Optional - if [0] == '-' { = [1:] if == "" { return false } } // Digits switch { default: return false case [0] == '0': = [1:] case '1' <= [0] && [0] <= '9': = [1:] for len() > 0 && '0' <= [0] && [0] <= '9' { = [1:] } } // . followed by 1 or more digits. if len() >= 2 && [0] == '.' && '0' <= [1] && [1] <= '9' { = [2:] for len() > 0 && '0' <= [0] && [0] <= '9' { = [1:] } } // e or E followed by an optional - or + and // 1 or more digits. if len() >= 2 && ([0] == 'e' || [0] == 'E') { = [1:] if [0] == '+' || [0] == '-' { = [1:] if == "" { return false } } for len() > 0 && '0' <= [0] && [0] <= '9' { = [1:] } } // Make sure we are at the end. return == "" } func interfaceEncoder( *encodeState, reflect.Value, encOpts) { if .IsNil() { .WriteString("null") return } .reflectValue(.Elem(), ) } func unsupportedTypeEncoder( *encodeState, reflect.Value, encOpts) { .error(&UnsupportedTypeError{.Type()}) } type structEncoder struct { fields structFields } type structFields struct { list []field nameIndex map[string]int } func ( structEncoder) ( *encodeState, reflect.Value, encOpts) { := byte('{') : for := range .fields.list { := &.fields.list[] // Find the nested struct field by following f.index. := for , := range .index { if .Kind() == reflect.Ptr { if .IsNil() { continue } = .Elem() } = .Field() } if .omitEmpty && isEmptyValue() { continue } .WriteByte() = ',' if .escapeHTML { .WriteString(.nameEscHTML) } else { .WriteString(.nameNonEsc) } .quoted = .quoted .encoder(, , ) } if == '{' { .WriteString("{}") } else { .WriteByte('}') } } func newStructEncoder( reflect.Type) encoderFunc { := structEncoder{fields: cachedTypeFields()} return .encode } type mapEncoder struct { elemEnc encoderFunc } func ( mapEncoder) ( *encodeState, reflect.Value, encOpts) { if .IsNil() { .WriteString("null") return } if .ptrLevel++; .ptrLevel > startDetectingCyclesAfter { // We're a large number of nested ptrEncoder.encode calls deep; // start checking if we've run into a pointer cycle. := .Pointer() if , := .ptrSeen[]; { .error(&UnsupportedValueError{, fmt.Sprintf("encountered a cycle via %s", .Type())}) } .ptrSeen[] = struct{}{} defer delete(.ptrSeen, ) } .WriteByte('{') // Extract and sort the keys. := .MapKeys() := make([]reflectWithString, len()) for , := range { [].v = if := [].resolve(); != nil { .error(fmt.Errorf("json: encoding error for type %q: %q", .Type().String(), .Error())) } } sort.Slice(, func(, int) bool { return [].s < [].s }) for , := range { if > 0 { .WriteByte(',') } .string(.s, .escapeHTML) .WriteByte(':') .elemEnc(, .MapIndex(.v), ) } .WriteByte('}') .ptrLevel-- } func newMapEncoder( reflect.Type) encoderFunc { switch .Key().Kind() { case reflect.String, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: default: if !.Key().Implements(textMarshalerType) { return unsupportedTypeEncoder } } := mapEncoder{typeEncoder(.Elem())} return .encode } func encodeByteSlice( *encodeState, reflect.Value, encOpts) { if .IsNil() { .WriteString("null") return } := .Bytes() .WriteByte('"') := base64.StdEncoding.EncodedLen(len()) if <= len(.scratch) { // If the encoded bytes fit in e.scratch, avoid an extra // allocation and use the cheaper Encoding.Encode. := .scratch[:] base64.StdEncoding.Encode(, ) .Write() } else if <= 1024 { // The encoded bytes are short enough to allocate for, and // Encoding.Encode is still cheaper. := make([]byte, ) base64.StdEncoding.Encode(, ) .Write() } else { // The encoded bytes are too long to cheaply allocate, and // Encoding.Encode is no longer noticeably cheaper. := base64.NewEncoder(base64.StdEncoding, ) .Write() .Close() } .WriteByte('"') } // sliceEncoder just wraps an arrayEncoder, checking to make sure the value isn't nil. type sliceEncoder struct { arrayEnc encoderFunc } func ( sliceEncoder) ( *encodeState, reflect.Value, encOpts) { if .IsNil() { .WriteString("null") return } if .ptrLevel++; .ptrLevel > startDetectingCyclesAfter { // We're a large number of nested ptrEncoder.encode calls deep; // start checking if we've run into a pointer cycle. // Here we use a struct to memorize the pointer to the first element of the slice // and its length. := struct { uintptr int }{.Pointer(), .Len()} if , := .ptrSeen[]; { .error(&UnsupportedValueError{, fmt.Sprintf("encountered a cycle via %s", .Type())}) } .ptrSeen[] = struct{}{} defer delete(.ptrSeen, ) } .arrayEnc(, , ) .ptrLevel-- } func newSliceEncoder( reflect.Type) encoderFunc { // Byte slices get special treatment; arrays don't. if .Elem().Kind() == reflect.Uint8 { := reflect.PtrTo(.Elem()) if !.Implements(marshalerType) && !.Implements(textMarshalerType) { return encodeByteSlice } } := sliceEncoder{newArrayEncoder()} return .encode } type arrayEncoder struct { elemEnc encoderFunc } func ( arrayEncoder) ( *encodeState, reflect.Value, encOpts) { .WriteByte('[') := .Len() for := 0; < ; ++ { if > 0 { .WriteByte(',') } .elemEnc(, .Index(), ) } .WriteByte(']') } func newArrayEncoder( reflect.Type) encoderFunc { := arrayEncoder{typeEncoder(.Elem())} return .encode } type ptrEncoder struct { elemEnc encoderFunc } func ( ptrEncoder) ( *encodeState, reflect.Value, encOpts) { if .IsNil() { .WriteString("null") return } if .ptrLevel++; .ptrLevel > startDetectingCyclesAfter { // We're a large number of nested ptrEncoder.encode calls deep; // start checking if we've run into a pointer cycle. := .Interface() if , := .ptrSeen[]; { .error(&UnsupportedValueError{, fmt.Sprintf("encountered a cycle via %s", .Type())}) } .ptrSeen[] = struct{}{} defer delete(.ptrSeen, ) } .elemEnc(, .Elem(), ) .ptrLevel-- } func newPtrEncoder( reflect.Type) encoderFunc { := ptrEncoder{typeEncoder(.Elem())} return .encode } type condAddrEncoder struct { canAddrEnc, elseEnc encoderFunc } func ( condAddrEncoder) ( *encodeState, reflect.Value, encOpts) { if .CanAddr() { .canAddrEnc(, , ) } else { .elseEnc(, , ) } } // newCondAddrEncoder returns an encoder that checks whether its value // CanAddr and delegates to canAddrEnc if so, else to elseEnc. func newCondAddrEncoder(, encoderFunc) encoderFunc { := condAddrEncoder{canAddrEnc: , elseEnc: } return .encode } func isValidTag( string) bool { if == "" { return false } for , := range { switch { case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", ): // Backslash and quote chars are reserved, but // otherwise any punctuation chars are allowed // in a tag name. case !unicode.IsLetter() && !unicode.IsDigit(): return false } } return true } func typeByIndex( reflect.Type, []int) reflect.Type { for , := range { if .Kind() == reflect.Ptr { = .Elem() } = .Field().Type } return } type reflectWithString struct { v reflect.Value s string } func ( *reflectWithString) () error { if .v.Kind() == reflect.String { .s = .v.String() return nil } if , := .v.Interface().(encoding.TextMarshaler); { if .v.Kind() == reflect.Ptr && .v.IsNil() { return nil } , := .MarshalText() .s = string() return } switch .v.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: .s = strconv.FormatInt(.v.Int(), 10) return nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: .s = strconv.FormatUint(.v.Uint(), 10) return nil } panic("unexpected map key type") } // NOTE: keep in sync with stringBytes below. func ( *encodeState) ( string, bool) { .WriteByte('"') := 0 for := 0; < len(); { if := []; < utf8.RuneSelf { if htmlSafeSet[] || (! && safeSet[]) { ++ continue } if < { .WriteString([:]) } .WriteByte('\\') switch { case '\\', '"': .WriteByte() case '\n': .WriteByte('n') case '\r': .WriteByte('r') case '\t': .WriteByte('t') default: // This encodes bytes < 0x20 except for \t, \n and \r. // If escapeHTML is set, it also escapes <, >, and & // because they can lead to security holes when // user-controlled strings are rendered into JSON // and served to some browsers. .WriteString(`u00`) .WriteByte(hex[>>4]) .WriteByte(hex[&0xF]) } ++ = continue } , := utf8.DecodeRuneInString([:]) if == utf8.RuneError && == 1 { if < { .WriteString([:]) } .WriteString(`\ufffd`) += = 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 == '\u2028' || == '\u2029' { if < { .WriteString([:]) } .WriteString(`\u202`) .WriteByte(hex[&0xF]) += = continue } += } if < len() { .WriteString([:]) } .WriteByte('"') } // NOTE: keep in sync with string above. func ( *encodeState) ( []byte, bool) { .WriteByte('"') := 0 for := 0; < len(); { if := []; < utf8.RuneSelf { if htmlSafeSet[] || (! && safeSet[]) { ++ continue } if < { .Write([:]) } .WriteByte('\\') switch { case '\\', '"': .WriteByte() case '\n': .WriteByte('n') case '\r': .WriteByte('r') case '\t': .WriteByte('t') default: // This encodes bytes < 0x20 except for \t, \n and \r. // If escapeHTML is set, it also escapes <, >, and & // because they can lead to security holes when // user-controlled strings are rendered into JSON // and served to some browsers. .WriteString(`u00`) .WriteByte(hex[>>4]) .WriteByte(hex[&0xF]) } ++ = continue } , := utf8.DecodeRune([:]) if == utf8.RuneError && == 1 { if < { .Write([:]) } .WriteString(`\ufffd`) += = 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 == '\u2028' || == '\u2029' { if < { .Write([:]) } .WriteString(`\u202`) .WriteByte(hex[&0xF]) += = continue } += } if < len() { .Write([:]) } .WriteByte('"') } // 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 nameNonEsc string // `"` + name + `":` nameEscHTML string // `"` + HTMLEscape(name) + `":` tag bool index []int typ reflect.Type omitEmpty bool quoted bool encoder encoderFunc } // byIndex sorts field by index sequence. type byIndex []field func ( byIndex) () int { return len() } func ( byIndex) (, int) { [], [] = [], [] } func ( byIndex) (, int) bool { for , := range [].index { if >= len([].index) { return false } if != [].index[] { return < [].index[] } } return len([].index) < len([].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( reflect.Type) structFields { // Anonymous fields to explore at the current level and the next. := []field{} := []field{{typ: }} // Count of queued names for current level and the next. var , map[reflect.Type]int // Types already visited at an earlier level. := map[reflect.Type]bool{} // Fields found. var []field // Buffer to run HTMLEscape on field names. var bytes.Buffer for len() > 0 { , = , [:0] , = , map[reflect.Type]int{} for , := range { if [.typ] { continue } [.typ] = true // Scan f.typ for fields to include. for := 0; < .typ.NumField(); ++ { := .typ.Field() := .PkgPath != "" if .Anonymous { := .Type if .Kind() == reflect.Ptr { = .Elem() } if && .Kind() != reflect.Struct { // Ignore embedded fields of unexported non-struct types. continue } // Do not ignore embedded fields of unexported struct types // since they may have exported fields. } else if { // Ignore unexported non-embedded fields. continue } := .Tag.Get("json") if == "-" { continue } , := parseTag() if !isValidTag() { = "" } := make([]int, len(.index)+1) copy(, .index) [len(.index)] = := .Type if .Name() == "" && .Kind() == reflect.Ptr { // Follow pointer. = .Elem() } // Only strings, floats, integers, and booleans can be quoted. := false if .Contains("string") { switch .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.Uintptr, reflect.Float32, reflect.Float64, reflect.String: = true } } // Record found field and index sequence. if != "" || !.Anonymous || .Kind() != reflect.Struct { := != "" if == "" { = .Name } := field{ name: , tag: , index: , typ: , omitEmpty: .Contains("omitempty"), quoted: , } .nameBytes = []byte(.name) .equalFold = foldFunc(.nameBytes) // Build nameEscHTML and nameNonEsc ahead of time. .Reset() .WriteString(`"`) HTMLEscape(&, .nameBytes) .WriteString(`":`) .nameEscHTML = .String() .nameNonEsc = `"` + .name + `":` = append(, ) if [.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. = append(, [len()-1]) } continue } // Record new anonymous struct to explore in next round. []++ if [] == 1 { = append(, field{name: .Name(), index: , typ: }) } } } } sort.Slice(, func(, int) bool { := // sort field by name, breaking ties with depth, then // breaking ties with "name came from json tag", then // breaking ties with index sequence. if [].name != [].name { return [].name < [].name } if len([].index) != len([].index) { return len([].index) < len([].index) } if [].tag != [].tag { return [].tag } return byIndex().Less(, ) }) // 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. := [:0] for , := 0, 0; < len(); += { // One iteration per name. // Find the sequence of fields with the name of this first field. := [] := .name for = 1; + < len(); ++ { := [+] if .name != { break } } if == 1 { // Only one field with this name = append(, ) continue } , := dominantField([ : +]) if { = append(, ) } } = sort.Sort(byIndex()) for := range { := &[] .encoder = typeEncoder(typeByIndex(, .index)) } := make(map[string]int, len()) for , := range { [.name] = } return structFields{, } } // 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( []field) (field, bool) { // The fields are sorted in increasing index-length order, then by presence of tag. // That means that the first field is the dominant one. We need only check // for error cases: two fields at top level, either both tagged or neither tagged. if len() > 1 && len([0].index) == len([1].index) && [0].tag == [1].tag { return field{}, false } return [0], true } var fieldCache sync.Map // map[reflect.Type]structFields // cachedTypeFields is like typeFields but uses a cache to avoid repeated work. func cachedTypeFields( reflect.Type) structFields { if , := fieldCache.Load(); { return .(structFields) } , := fieldCache.LoadOrStore(, typeFields()) return .(structFields) }