1package json 2 3import ( 4 "bytes" 5 "encoding/json" 6 "io" 7 "math/bits" 8 "reflect" 9 "runtime" 10 "sync" 11 "unsafe" 12) 13 14// Delim is documented at https://golang.org/pkg/encoding/json/#Delim 15type Delim = json.Delim 16 17// InvalidUTF8Error is documented at https://golang.org/pkg/encoding/json/#InvalidUTF8Error 18type InvalidUTF8Error = json.InvalidUTF8Error 19 20// InvalidUnmarshalError is documented at https://golang.org/pkg/encoding/json/#InvalidUnmarshalError 21type InvalidUnmarshalError = json.InvalidUnmarshalError 22 23// Marshaler is documented at https://golang.org/pkg/encoding/json/#Marshaler 24type Marshaler = json.Marshaler 25 26// MarshalerError is documented at https://golang.org/pkg/encoding/json/#MarshalerError 27type MarshalerError = json.MarshalerError 28 29// Number is documented at https://golang.org/pkg/encoding/json/#Number 30type Number = json.Number 31 32// RawMessage is documented at https://golang.org/pkg/encoding/json/#RawMessage 33type RawMessage = json.RawMessage 34 35// A SyntaxError is a description of a JSON syntax error. 36type SyntaxError = json.SyntaxError 37 38// Token is documented at https://golang.org/pkg/encoding/json/#Token 39type Token = json.Token 40 41// UnmarshalFieldError is documented at https://golang.org/pkg/encoding/json/#UnmarshalFieldError 42type UnmarshalFieldError = json.UnmarshalFieldError 43 44// UnmarshalTypeError is documented at https://golang.org/pkg/encoding/json/#UnmarshalTypeError 45type UnmarshalTypeError = json.UnmarshalTypeError 46 47// Unmarshaler is documented at https://golang.org/pkg/encoding/json/#Unmarshaler 48type Unmarshaler = json.Unmarshaler 49 50// UnsupportedTypeError is documented at https://golang.org/pkg/encoding/json/#UnsupportedTypeError 51type UnsupportedTypeError = json.UnsupportedTypeError 52 53// UnsupportedValueError is documented at https://golang.org/pkg/encoding/json/#UnsupportedValueError 54type UnsupportedValueError = json.UnsupportedValueError 55 56// AppendFlags is a type used to represent configuration options that can be 57// applied when formatting json output. 58type AppendFlags uint 59 60const ( 61 // EscapeHTML is a formatting flag used to to escape HTML in json strings. 62 EscapeHTML AppendFlags = 1 << iota 63 64 // SortMapKeys is formatting flag used to enable sorting of map keys when 65 // encoding JSON (this matches the behavior of the standard encoding/json 66 // package). 67 SortMapKeys 68 69 // TrustRawMessage is a performance optimization flag to skip value 70 // checking of raw messages. It should only be used if the values are 71 // known to be valid json (e.g., they were created by json.Unmarshal). 72 TrustRawMessage 73) 74 75// ParseFlags is a type used to represent configuration options that can be 76// applied when parsing json input. 77type ParseFlags uint 78 79func (flags ParseFlags) has(f ParseFlags) bool { 80 return (flags & f) != 0 81} 82 83func (f ParseFlags) kind() Kind { 84 return Kind((f >> kindOffset) & 0xFF) 85} 86 87func (f ParseFlags) withKind(kind Kind) ParseFlags { 88 return (f & ^(ParseFlags(0xFF) << kindOffset)) | (ParseFlags(kind) << kindOffset) 89} 90 91const ( 92 // DisallowUnknownFields is a parsing flag used to prevent decoding of 93 // objects to Go struct values when a field of the input does not match 94 // with any of the struct fields. 95 DisallowUnknownFields ParseFlags = 1 << iota 96 97 // UseNumber is a parsing flag used to load numeric values as Number 98 // instead of float64. 99 UseNumber 100 101 // DontCopyString is a parsing flag used to provide zero-copy support when 102 // loading string values from a json payload. It is not always possible to 103 // avoid dynamic memory allocations, for example when a string is escaped in 104 // the json data a new buffer has to be allocated, but when the `wire` value 105 // can be used as content of a Go value the decoder will simply point into 106 // the input buffer. 107 DontCopyString 108 109 // DontCopyNumber is a parsing flag used to provide zero-copy support when 110 // loading Number values (see DontCopyString and DontCopyRawMessage). 111 DontCopyNumber 112 113 // DontCopyRawMessage is a parsing flag used to provide zero-copy support 114 // when loading RawMessage values from a json payload. When used, the 115 // RawMessage values will not be allocated into new memory buffers and 116 // will instead point directly to the area of the input buffer where the 117 // value was found. 118 DontCopyRawMessage 119 120 // DontMatchCaseInsensitiveStructFields is a parsing flag used to prevent 121 // matching fields in a case-insensitive way. This can prevent degrading 122 // performance on case conversions, and can also act as a stricter decoding 123 // mode. 124 DontMatchCaseInsensitiveStructFields 125 126 // ZeroCopy is a parsing flag that combines all the copy optimizations 127 // available in the package. 128 // 129 // The zero-copy optimizations are better used in request-handler style 130 // code where none of the values are retained after the handler returns. 131 ZeroCopy = DontCopyString | DontCopyNumber | DontCopyRawMessage 132 133 // validAsciiPrint is an internal flag indicating that the input contains 134 // only valid ASCII print chars (0x20 <= c <= 0x7E). If the flag is unset, 135 // it's unknown whether the input is valid ASCII print. 136 validAsciiPrint ParseFlags = 1 << 28 137 138 // noBackslach is an internal flag indicating that the input does not 139 // contain a backslash. If the flag is unset, it's unknown whether the 140 // input contains a backslash. 141 noBackslash ParseFlags = 1 << 29 142 143 // Bit offset where the kind of the json value is stored. 144 // 145 // See Kind in token.go for the enum. 146 kindOffset ParseFlags = 16 147) 148 149// Kind represents the different kinds of value that exist in JSON. 150type Kind uint 151 152const ( 153 Undefined Kind = 0 154 155 Null Kind = 1 // Null is not zero, so we keep zero for "undefined". 156 157 Bool Kind = 2 // Bit two is set to 1, means it's a boolean. 158 False Kind = 2 // Bool + 0 159 True Kind = 3 // Bool + 1 160 161 Num Kind = 4 // Bit three is set to 1, means it's a number. 162 Uint Kind = 5 // Num + 1 163 Int Kind = 6 // Num + 2 164 Float Kind = 7 // Num + 3 165 166 String Kind = 8 // Bit four is set to 1, means it's a string. 167 Unescaped Kind = 9 // String + 1 168 169 Array Kind = 16 // Equivalent to Delim == '[' 170 Object Kind = 32 // Equivalent to Delim == '{' 171) 172 173// Class returns the class of k. 174func (k Kind) Class() Kind { return Kind(1 << uint(bits.Len(uint(k))-1)) } 175 176// Append acts like Marshal but appends the json representation to b instead of 177// always reallocating a new slice. 178func Append(b []byte, x interface{}, flags AppendFlags) ([]byte, error) { 179 if x == nil { 180 // Special case for nil values because it makes the rest of the code 181 // simpler to assume that it won't be seeing nil pointers. 182 return append(b, "null"...), nil 183 } 184 185 t := reflect.TypeOf(x) 186 p := (*iface)(unsafe.Pointer(&x)).ptr 187 188 cache := cacheLoad() 189 c, found := cache[typeid(t)] 190 191 if !found { 192 c = constructCachedCodec(t, cache) 193 } 194 195 b, err := c.encode(encoder{flags: flags}, b, p) 196 runtime.KeepAlive(x) 197 return b, err 198} 199 200// Escape is a convenience helper to construct an escaped JSON string from s. 201// The function escales HTML characters, for more control over the escape 202// behavior and to write to a pre-allocated buffer, use AppendEscape. 203func Escape(s string) []byte { 204 // +10 for extra escape characters, maybe not enough and the buffer will 205 // be reallocated. 206 b := make([]byte, 0, len(s)+10) 207 return AppendEscape(b, s, EscapeHTML) 208} 209 210// AppendEscape appends s to b with the string escaped as a JSON value. 211// This will include the starting and ending quote characters, and the 212// appropriate characters will be escaped correctly for JSON encoding. 213func AppendEscape(b []byte, s string, flags AppendFlags) []byte { 214 e := encoder{flags: flags} 215 b, _ = e.encodeString(b, unsafe.Pointer(&s)) 216 return b 217} 218 219// Unescape is a convenience helper to unescape a JSON value. 220// For more control over the unescape behavior and 221// to write to a pre-allocated buffer, use AppendUnescape. 222func Unescape(s []byte) []byte { 223 b := make([]byte, 0, len(s)) 224 return AppendUnescape(b, s, ParseFlags(0)) 225} 226 227// AppendUnescape appends s to b with the string unescaped as a JSON value. 228// This will remove starting and ending quote characters, and the 229// appropriate characters will be escaped correctly as if JSON decoded. 230// New space will be reallocated if more space is needed. 231func AppendUnescape(b []byte, s []byte, flags ParseFlags) []byte { 232 d := decoder{flags: flags} 233 buf := new(string) 234 d.decodeString(s, unsafe.Pointer(buf)) 235 return append(b, *buf...) 236} 237 238// Compact is documented at https://golang.org/pkg/encoding/json/#Compact 239func Compact(dst *bytes.Buffer, src []byte) error { 240 return json.Compact(dst, src) 241} 242 243// HTMLEscape is documented at https://golang.org/pkg/encoding/json/#HTMLEscape 244func HTMLEscape(dst *bytes.Buffer, src []byte) { 245 json.HTMLEscape(dst, src) 246} 247 248// Indent is documented at https://golang.org/pkg/encoding/json/#Indent 249func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error { 250 return json.Indent(dst, src, prefix, indent) 251} 252 253// Marshal is documented at https://golang.org/pkg/encoding/json/#Marshal 254func Marshal(x interface{}) ([]byte, error) { 255 var err error 256 var buf = encoderBufferPool.Get().(*encoderBuffer) 257 258 if buf.data, err = Append(buf.data[:0], x, EscapeHTML|SortMapKeys); err != nil { 259 return nil, err 260 } 261 262 b := make([]byte, len(buf.data)) 263 copy(b, buf.data) 264 encoderBufferPool.Put(buf) 265 return b, nil 266} 267 268// MarshalIndent is documented at https://golang.org/pkg/encoding/json/#MarshalIndent 269func MarshalIndent(x interface{}, prefix, indent string) ([]byte, error) { 270 b, err := Marshal(x) 271 272 if err == nil { 273 tmp := &bytes.Buffer{} 274 tmp.Grow(2 * len(b)) 275 276 Indent(tmp, b, prefix, indent) 277 b = tmp.Bytes() 278 } 279 280 return b, err 281} 282 283// Unmarshal is documented at https://golang.org/pkg/encoding/json/#Unmarshal 284func Unmarshal(b []byte, x interface{}) error { 285 r, err := Parse(b, x, 0) 286 if len(r) != 0 { 287 if _, ok := err.(*SyntaxError); !ok { 288 // The encoding/json package prioritizes reporting errors caused by 289 // unexpected trailing bytes over other issues; here we emulate this 290 // behavior by overriding the error. 291 err = syntaxError(r, "invalid character '%c' after top-level value", r[0]) 292 } 293 } 294 return err 295} 296 297// Parse behaves like Unmarshal but the caller can pass a set of flags to 298// configure the parsing behavior. 299func Parse(b []byte, x interface{}, flags ParseFlags) ([]byte, error) { 300 t := reflect.TypeOf(x) 301 p := (*iface)(unsafe.Pointer(&x)).ptr 302 303 d := decoder{flags: flags | internalParseFlags(b)} 304 305 b = skipSpaces(b) 306 307 if t == nil || p == nil || t.Kind() != reflect.Ptr { 308 _, r, _, err := d.parseValue(b) 309 r = skipSpaces(r) 310 if err != nil { 311 return r, err 312 } 313 return r, &InvalidUnmarshalError{Type: t} 314 } 315 t = t.Elem() 316 317 cache := cacheLoad() 318 c, found := cache[typeid(t)] 319 320 if !found { 321 c = constructCachedCodec(t, cache) 322 } 323 324 r, err := c.decode(d, b, p) 325 return skipSpaces(r), err 326} 327 328// Valid is documented at https://golang.org/pkg/encoding/json/#Valid 329func Valid(data []byte) bool { 330 data = skipSpaces(data) 331 d := decoder{flags: internalParseFlags(data)} 332 _, data, _, err := d.parseValue(data) 333 if err != nil { 334 return false 335 } 336 return len(skipSpaces(data)) == 0 337} 338 339// Decoder is documented at https://golang.org/pkg/encoding/json/#Decoder 340type Decoder struct { 341 reader io.Reader 342 buffer []byte 343 remain []byte 344 inputOffset int64 345 err error 346 flags ParseFlags 347} 348 349// NewDecoder is documented at https://golang.org/pkg/encoding/json/#NewDecoder 350func NewDecoder(r io.Reader) *Decoder { return &Decoder{reader: r} } 351 352// Buffered is documented at https://golang.org/pkg/encoding/json/#Decoder.Buffered 353func (dec *Decoder) Buffered() io.Reader { 354 return bytes.NewReader(dec.remain) 355} 356 357// Decode is documented at https://golang.org/pkg/encoding/json/#Decoder.Decode 358func (dec *Decoder) Decode(v interface{}) error { 359 raw, err := dec.readValue() 360 if err != nil { 361 return err 362 } 363 _, err = Parse(raw, v, dec.flags) 364 return err 365} 366 367const ( 368 minBufferSize = 32768 369 minReadSize = 4096 370) 371 372// readValue reads one JSON value from the buffer and returns its raw bytes. It 373// is optimized for the "one JSON value per line" case. 374func (dec *Decoder) readValue() (v []byte, err error) { 375 var n int 376 var r []byte 377 d := decoder{flags: dec.flags} 378 379 for { 380 if len(dec.remain) != 0 { 381 v, r, _, err = d.parseValue(dec.remain) 382 if err == nil { 383 dec.remain, n = skipSpacesN(r) 384 dec.inputOffset += int64(len(v) + n) 385 return 386 } 387 if len(r) != 0 { 388 // Parsing of the next JSON value stopped at a position other 389 // than the end of the input buffer, which indicaates that a 390 // syntax error was encountered. 391 return 392 } 393 } 394 395 if err = dec.err; err != nil { 396 if len(dec.remain) != 0 && err == io.EOF { 397 err = io.ErrUnexpectedEOF 398 } 399 return 400 } 401 402 if dec.buffer == nil { 403 dec.buffer = make([]byte, 0, minBufferSize) 404 } else { 405 dec.buffer = dec.buffer[:copy(dec.buffer[:cap(dec.buffer)], dec.remain)] 406 dec.remain = nil 407 } 408 409 if (cap(dec.buffer) - len(dec.buffer)) < minReadSize { 410 buf := make([]byte, len(dec.buffer), 2*cap(dec.buffer)) 411 copy(buf, dec.buffer) 412 dec.buffer = buf 413 } 414 415 n, err = io.ReadFull(dec.reader, dec.buffer[len(dec.buffer):cap(dec.buffer)]) 416 if n > 0 { 417 dec.buffer = dec.buffer[:len(dec.buffer)+n] 418 if err != nil { 419 err = nil 420 } 421 } else if err == io.ErrUnexpectedEOF { 422 err = io.EOF 423 } 424 dec.remain, n = skipSpacesN(dec.buffer) 425 d.flags = dec.flags | internalParseFlags(dec.remain) 426 dec.inputOffset += int64(n) 427 dec.err = err 428 } 429} 430 431// DisallowUnknownFields is documented at https://golang.org/pkg/encoding/json/#Decoder.DisallowUnknownFields 432func (dec *Decoder) DisallowUnknownFields() { dec.flags |= DisallowUnknownFields } 433 434// UseNumber is documented at https://golang.org/pkg/encoding/json/#Decoder.UseNumber 435func (dec *Decoder) UseNumber() { dec.flags |= UseNumber } 436 437// DontCopyString is an extension to the standard encoding/json package 438// which instructs the decoder to not copy strings loaded from the json 439// payloads when possible. 440func (dec *Decoder) DontCopyString() { dec.flags |= DontCopyString } 441 442// DontCopyNumber is an extension to the standard encoding/json package 443// which instructs the decoder to not copy numbers loaded from the json 444// payloads. 445func (dec *Decoder) DontCopyNumber() { dec.flags |= DontCopyNumber } 446 447// DontCopyRawMessage is an extension to the standard encoding/json package 448// which instructs the decoder to not allocate RawMessage values in separate 449// memory buffers (see the documentation of the DontcopyRawMessage flag for 450// more detais). 451func (dec *Decoder) DontCopyRawMessage() { dec.flags |= DontCopyRawMessage } 452 453// DontMatchCaseInsensitiveStructFields is an extension to the standard 454// encoding/json package which instructs the decoder to not match object fields 455// against struct fields in a case-insensitive way, the field names have to 456// match exactly to be decoded into the struct field values. 457func (dec *Decoder) DontMatchCaseInsensitiveStructFields() { 458 dec.flags |= DontMatchCaseInsensitiveStructFields 459} 460 461// ZeroCopy is an extension to the standard encoding/json package which enables 462// all the copy optimizations of the decoder. 463func (dec *Decoder) ZeroCopy() { dec.flags |= ZeroCopy } 464 465// InputOffset returns the input stream byte offset of the current decoder position. 466// The offset gives the location of the end of the most recently returned token 467// and the beginning of the next token. 468func (dec *Decoder) InputOffset() int64 { 469 return dec.inputOffset 470} 471 472// Encoder is documented at https://golang.org/pkg/encoding/json/#Encoder 473type Encoder struct { 474 writer io.Writer 475 prefix string 476 indent string 477 buffer *bytes.Buffer 478 err error 479 flags AppendFlags 480} 481 482// NewEncoder is documented at https://golang.org/pkg/encoding/json/#NewEncoder 483func NewEncoder(w io.Writer) *Encoder { return &Encoder{writer: w, flags: EscapeHTML | SortMapKeys} } 484 485// Encode is documented at https://golang.org/pkg/encoding/json/#Encoder.Encode 486func (enc *Encoder) Encode(v interface{}) error { 487 if enc.err != nil { 488 return enc.err 489 } 490 491 var err error 492 var buf = encoderBufferPool.Get().(*encoderBuffer) 493 494 buf.data, err = Append(buf.data[:0], v, enc.flags) 495 496 if err != nil { 497 encoderBufferPool.Put(buf) 498 return err 499 } 500 501 buf.data = append(buf.data, '\n') 502 b := buf.data 503 504 if enc.prefix != "" || enc.indent != "" { 505 if enc.buffer == nil { 506 enc.buffer = new(bytes.Buffer) 507 enc.buffer.Grow(2 * len(buf.data)) 508 } else { 509 enc.buffer.Reset() 510 } 511 Indent(enc.buffer, buf.data, enc.prefix, enc.indent) 512 b = enc.buffer.Bytes() 513 } 514 515 if _, err := enc.writer.Write(b); err != nil { 516 enc.err = err 517 } 518 519 encoderBufferPool.Put(buf) 520 return err 521} 522 523// SetEscapeHTML is documented at https://golang.org/pkg/encoding/json/#Encoder.SetEscapeHTML 524func (enc *Encoder) SetEscapeHTML(on bool) { 525 if on { 526 enc.flags |= EscapeHTML 527 } else { 528 enc.flags &= ^EscapeHTML 529 } 530} 531 532// SetIndent is documented at https://golang.org/pkg/encoding/json/#Encoder.SetIndent 533func (enc *Encoder) SetIndent(prefix, indent string) { 534 enc.prefix = prefix 535 enc.indent = indent 536} 537 538// SetSortMapKeys is an extension to the standard encoding/json package which 539// allows the program to toggle sorting of map keys on and off. 540func (enc *Encoder) SetSortMapKeys(on bool) { 541 if on { 542 enc.flags |= SortMapKeys 543 } else { 544 enc.flags &= ^SortMapKeys 545 } 546} 547 548// SetTrustRawMessage skips value checking when encoding a raw json message. It should only 549// be used if the values are known to be valid json, e.g. because they were originally created 550// by json.Unmarshal. 551func (enc *Encoder) SetTrustRawMessage(on bool) { 552 if on { 553 enc.flags |= TrustRawMessage 554 } else { 555 enc.flags &= ^TrustRawMessage 556 } 557} 558 559var encoderBufferPool = sync.Pool{ 560 New: func() interface{} { return &encoderBuffer{data: make([]byte, 0, 4096)} }, 561} 562 563type encoderBuffer struct{ data []byte } 564