| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- // Copyright 2018 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 the JSON format.
- // This package has no semantic understanding for protocol buffers and is only
- // a parser and composer for the format.
- //
- // This follows RFC 7159, with some notable implementation specifics:
- // * numbers that are out of range result in a decoding error
- // * duplicate keys in objects are not rejected
- //
- // Reasons why the standard encoding/json package is not suitable:
- // * information about duplicate keys is lost
- // * invalid UTF-8 is silently coerced into utf8.RuneError
- package json
- import (
- "fmt"
- "strings"
- )
- // Type represents a type expressible in the JSON format.
- type Type uint8
- const (
- _ Type = iota
- // Null is the null literal (i.e., "null").
- Null
- // Bool is a boolean (i.e., "true" or "false").
- Bool
- // Number is a floating-point number (e.g., "1.234" or "1e100").
- Number
- // String is an escaped string (e.g., `"the quick brown fox"`).
- String
- // Array is an ordered list of values (e.g., `[0, "one", true]`).
- Array
- // Object is an ordered map of values (e.g., `{"key": null}`).
- Object
- )
- func (t Type) String() string {
- switch t {
- case Null:
- return "null"
- case Bool:
- return "bool"
- case Number:
- return "number"
- case String:
- return "string"
- case Array:
- return "array"
- case Object:
- return "object"
- default:
- return "<invalid>"
- }
- }
- // Value contains a value of a given Type.
- type Value struct {
- typ Type
- raw []byte // raw bytes of the serialized data
- str string // only for String
- num float64 // only for Bool or Number
- arr []Value // only for Array
- obj [][2]Value // only for Object
- }
- // ValueOf returns a Value for a given Go value:
- // nil => Null
- // bool => Bool
- // int32, int64 => Number
- // uint32, uint64 => Number
- // float32, float64 => Number
- // string, []byte => String
- // []Value => Array
- // [][2]Value => Object
- //
- // ValueOf panics if the Go type is not one of the above.
- func ValueOf(v interface{}) Value {
- switch v := v.(type) {
- case nil:
- return Value{typ: Null}
- case bool:
- if v {
- return Value{typ: Bool, num: 1}
- } else {
- return Value{typ: Bool, num: 0}
- }
- case int32:
- return Value{typ: Number, num: float64(v)}
- case int64:
- return Value{typ: Number, num: float64(v)} // possible loss of precision
- case uint32:
- return Value{typ: Number, num: float64(v)}
- case uint64:
- return Value{typ: Number, num: float64(v)} // possible loss of precision
- case float32:
- return Value{typ: Number, num: float64(v)}
- case float64:
- return Value{typ: Number, num: float64(v)}
- case string:
- return Value{typ: String, str: string(v)}
- case []byte:
- return Value{typ: String, str: string(v)}
- case []Value:
- return Value{typ: Array, arr: v}
- case [][2]Value:
- return Value{typ: Object, obj: v}
- default:
- panic(fmt.Sprintf("invalid type %T", v))
- }
- }
- func rawValueOf(v interface{}, raw []byte) Value {
- v2 := ValueOf(v)
- v2.raw = raw
- return v2
- }
- // Type is the type of the value.
- func (v Value) Type() Type {
- return v.typ
- }
- // Bool returns v as a bool and panics if it is not a Bool.
- func (v Value) Bool() bool {
- if v.typ != Bool {
- panic("value is not a boolean")
- }
- return v.num != 0
- }
- // Number returns v as a float64 and panics if it is not a Number.
- func (v Value) Number() float64 {
- if v.typ != Number {
- panic("value is not a number")
- }
- return v.num
- }
- // String returns v as a string if the Type is String.
- // Otherwise, this returns a formatted string of v for debugging purposes.
- //
- // Since JSON strings must be UTF-8, the marshaler and unmarshaler will verify
- // for UTF-8 correctness.
- func (v Value) String() string {
- if v.typ != String {
- return v.stringValue()
- }
- return v.str
- }
- func (v Value) stringValue() string {
- switch v.typ {
- case Null, Bool, Number:
- return string(v.Raw())
- case Array:
- var ss []string
- for _, v := range v.Array() {
- ss = append(ss, v.String())
- }
- return "[" + strings.Join(ss, ",") + "]"
- case Object:
- var ss []string
- for _, v := range v.Object() {
- ss = append(ss, v[0].String()+":"+v[1].String())
- }
- return "{" + strings.Join(ss, ",") + "}"
- default:
- return "<invalid>"
- }
- }
- // Array returns the elements of v and panics if the Type is not Array.
- // Mutations on the return value may not be observable from the Raw method.
- func (v Value) Array() []Value {
- if v.typ != Array {
- panic("value is not an array")
- }
- return v.arr
- }
- // Object returns the items of v and panics if the Type is not Object.
- // The [2]Value represents a key (of type String) and value pair.
- //
- // Mutations on the return value may not be observable from the Raw method.
- func (v Value) Object() [][2]Value {
- if v.typ != Object {
- panic("value is not an object")
- }
- return v.obj
- }
- // Raw returns the raw representation of the value.
- // The returned value may alias the input given to Unmarshal.
- func (v Value) Raw() []byte {
- if len(v.raw) > 0 {
- return v.raw
- }
- p := encoder{}
- if err := p.marshalValue(v); !p.nerr.Merge(err) {
- return []byte("<invalid>")
- }
- return p.out
- }
|