github.com/grbit/go-json@v0.11.0/json.go (about) 1 package json 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 8 "github.com/grbit/go-json/internal/encoder" 9 ) 10 11 // Marshaler is the interface implemented by types that 12 // can marshal themselves into valid JSON. 13 type Marshaler interface { 14 MarshalJSON() ([]byte, error) 15 } 16 17 // MarshalerContext is the interface implemented by types that 18 // can marshal themselves into valid JSON with context.Context. 19 type MarshalerContext interface { 20 MarshalJSON(context.Context) ([]byte, error) 21 } 22 23 // Unmarshaler is the interface implemented by types 24 // that can unmarshal a JSON description of themselves. 25 // The input can be assumed to be a valid encoding of 26 // a JSON value. UnmarshalJSON must copy the JSON data 27 // if it wishes to retain the data after returning. 28 // 29 // By convention, to approximate the behavior of Unmarshal itself, 30 // Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op. 31 type Unmarshaler interface { 32 UnmarshalJSON([]byte) error 33 } 34 35 // UnmarshalerContext is the interface implemented by types 36 // that can unmarshal with context.Context a JSON description of themselves. 37 type UnmarshalerContext interface { 38 UnmarshalJSON(context.Context, []byte) error 39 } 40 41 // Marshal returns the JSON encoding of v. 42 // 43 // Marshal traverses the value v recursively. 44 // If an encountered value implements the Marshaler interface 45 // and is not a nil pointer, Marshal calls its MarshalJSON method 46 // to produce JSON. If no MarshalJSON method is present but the 47 // value implements encoding.TextMarshaler instead, Marshal calls 48 // its MarshalText method and encodes the result as a JSON string. 49 // The nil pointer exception is not strictly necessary 50 // but mimics a similar, necessary exception in the behavior of 51 // UnmarshalJSON. 52 // 53 // Otherwise, Marshal uses the following type-dependent default encodings: 54 // 55 // Boolean values encode as JSON booleans. 56 // 57 // Floating point, integer, and Number values encode as JSON numbers. 58 // 59 // String values encode as JSON strings coerced to valid UTF-8, 60 // replacing invalid bytes with the Unicode replacement rune. 61 // The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e" 62 // to keep some browsers from misinterpreting JSON output as HTML. 63 // Ampersand "&" is also escaped to "\u0026" for the same reason. 64 // This escaping can be disabled using an Encoder that had SetEscapeHTML(false) 65 // called on it. 66 // 67 // Array and slice values encode as JSON arrays, except that 68 // []byte encodes as a base64-encoded string, and a nil slice 69 // encodes as the null JSON value. 70 // 71 // Struct values encode as JSON objects. 72 // Each exported struct field becomes a member of the object, using the 73 // field name as the object key, unless the field is omitted for one of the 74 // reasons given below. 75 // 76 // The encoding of each struct field can be customized by the format string 77 // stored under the "json" key in the struct field's tag. 78 // The format string gives the name of the field, possibly followed by a 79 // comma-separated list of options. The name may be empty in order to 80 // specify options without overriding the default field name. 81 // 82 // The "omitempty" option specifies that the field should be omitted 83 // from the encoding if the field has an empty value, defined as 84 // false, 0, a nil pointer, a nil interface value, and any empty array, 85 // slice, map, or string. 86 // 87 // As a special case, if the field tag is "-", the field is always omitted. 88 // Note that a field with name "-" can still be generated using the tag "-,". 89 // 90 // Examples of struct field tags and their meanings: 91 // 92 // // Field appears in JSON as key "myName". 93 // Field int `json:"myName"` 94 // 95 // // Field appears in JSON as key "myName" and 96 // // the field is omitted from the object if its value is empty, 97 // // as defined above. 98 // Field int `json:"myName,omitempty"` 99 // 100 // // Field appears in JSON as key "Field" (the default), but 101 // // the field is skipped if empty. 102 // // Note the leading comma. 103 // Field int `json:",omitempty"` 104 // 105 // // Field is ignored by this package. 106 // Field int `json:"-"` 107 // 108 // // Field appears in JSON as key "-". 109 // Field int `json:"-,"` 110 // 111 // The "string" option signals that a field is stored as JSON inside a 112 // JSON-encoded string. It applies only to fields of string, floating point, 113 // integer, or boolean types. This extra level of encoding is sometimes used 114 // when communicating with JavaScript programs: 115 // 116 // Int64String int64 `json:",string"` 117 // 118 // The key name will be used if it's a non-empty string consisting of 119 // only Unicode letters, digits, and ASCII punctuation except quotation 120 // marks, backslash, and comma. 121 // 122 // Anonymous struct fields are usually marshaled as if their inner exported fields 123 // were fields in the outer struct, subject to the usual Go visibility rules amended 124 // as described in the next paragraph. 125 // An anonymous struct field with a name given in its JSON tag is treated as 126 // having that name, rather than being anonymous. 127 // An anonymous struct field of interface type is treated the same as having 128 // that type as its name, rather than being anonymous. 129 // 130 // The Go visibility rules for struct fields are amended for JSON when 131 // deciding which field to marshal or unmarshal. If there are 132 // multiple fields at the same level, and that level is the least 133 // nested (and would therefore be the nesting level selected by the 134 // usual Go rules), the following extra rules apply: 135 // 136 // 1) Of those fields, if any are JSON-tagged, only tagged fields are considered, 137 // even if there are multiple untagged fields that would otherwise conflict. 138 // 139 // 2) If there is exactly one field (tagged or not according to the first rule), that is selected. 140 // 141 // 3) Otherwise there are multiple fields, and all are ignored; no error occurs. 142 // 143 // Handling of anonymous struct fields is new in Go 1.1. 144 // Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of 145 // an anonymous struct field in both current and earlier versions, give the field 146 // a JSON tag of "-". 147 // 148 // Map values encode as JSON objects. The map's key type must either be a 149 // string, an integer type, or implement encoding.TextMarshaler. The map keys 150 // are sorted and used as JSON object keys by applying the following rules, 151 // subject to the UTF-8 coercion described for string values above: 152 // - string keys are used directly 153 // - encoding.TextMarshalers are marshaled 154 // - integer keys are converted to strings 155 // 156 // Pointer values encode as the value pointed to. 157 // A nil pointer encodes as the null JSON value. 158 // 159 // Interface values encode as the value contained in the interface. 160 // A nil interface value encodes as the null JSON value. 161 // 162 // Channel, complex, and function values cannot be encoded in JSON. 163 // Attempting to encode such a value causes Marshal to return 164 // an UnsupportedTypeError. 165 // 166 // JSON cannot represent cyclic data structures and Marshal does not 167 // handle them. Passing cyclic structures to Marshal will result in 168 // an infinite recursion. 169 func Marshal(v interface{}) (b []byte, err error) { 170 defer func() { 171 if r := recover(); r != nil { 172 b, err = json.Marshal(v) 173 174 return 175 } 176 }() 177 178 b, err = MarshalWithOption(v) 179 if err != nil { 180 b, err = json.Marshal(v) 181 } 182 183 return b, err 184 } 185 186 // MarshalNoEscape returns the JSON encoding of v and doesn't escape v. 187 func MarshalNoEscape(v interface{}) ([]byte, error) { 188 return marshalNoEscape(v) 189 } 190 191 // MarshalContext returns the JSON encoding of v with context.Context and EncodeOption. 192 func MarshalContext(ctx context.Context, v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) { 193 return marshalContext(ctx, v, optFuncs...) 194 } 195 196 // MarshalWithOption returns the JSON encoding of v with EncodeOption. 197 func MarshalWithOption(v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) { 198 return marshal(v, optFuncs...) 199 } 200 201 // MarshalIndent is like Marshal but applies Indent to format the output. 202 // Each JSON element in the output will begin on a new line beginning with prefix 203 // followed by one or more copies of indent according to the indentation nesting. 204 func MarshalIndent(v interface{}, prefix, indent string) (b []byte, err error) { 205 defer func() { 206 if r := recover(); r != nil { 207 b, err = json.MarshalIndent(v, prefix, indent) 208 209 return 210 } 211 }() 212 213 b, err = MarshalIndentWithOption(v, prefix, indent) 214 if err != nil { 215 b, err = json.MarshalIndent(v, prefix, indent) 216 } 217 218 return b, err 219 } 220 221 // MarshalIndentWithOption is like Marshal but applies Indent to format the output with EncodeOption. 222 func MarshalIndentWithOption(v interface{}, prefix, indent string, optFuncs ...EncodeOptionFunc) ([]byte, error) { 223 return marshalIndent(v, prefix, indent, optFuncs...) 224 } 225 226 // Unmarshal parses the JSON-encoded data and stores the result 227 // in the value pointed to by v. If v is nil or not a pointer, 228 // Unmarshal returns an InvalidUnmarshalError. 229 // 230 // Unmarshal uses the inverse of the encodings that 231 // Marshal uses, allocating maps, slices, and pointers as necessary, 232 // with the following additional rules: 233 // 234 // To unmarshal JSON into a pointer, Unmarshal first handles the case of 235 // the JSON being the JSON literal null. In that case, Unmarshal sets 236 // the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into 237 // the value pointed at by the pointer. If the pointer is nil, Unmarshal 238 // allocates a new value for it to point to. 239 // 240 // To unmarshal JSON into a value implementing the Unmarshaler interface, 241 // Unmarshal calls that value's UnmarshalJSON method, including 242 // when the input is a JSON null. 243 // Otherwise, if the value implements encoding.TextUnmarshaler 244 // and the input is a JSON quoted string, Unmarshal calls that value's 245 // UnmarshalText method with the unquoted form of the string. 246 // 247 // To unmarshal JSON into a struct, Unmarshal matches incoming object 248 // keys to the keys used by Marshal (either the struct field name or its tag), 249 // preferring an exact match but also accepting a case-insensitive match. By 250 // default, object keys which don't have a corresponding struct field are 251 // ignored (see Decoder.DisallowUnknownFields for an alternative). 252 // 253 // To unmarshal JSON into an interface value, 254 // Unmarshal stores one of these in the interface value: 255 // 256 // bool, for JSON booleans 257 // float64, for JSON numbers 258 // string, for JSON strings 259 // []interface{}, for JSON arrays 260 // map[string]interface{}, for JSON objects 261 // nil for JSON null 262 // 263 // To unmarshal a JSON array into a slice, Unmarshal resets the slice length 264 // to zero and then appends each element to the slice. 265 // As a special case, to unmarshal an empty JSON array into a slice, 266 // Unmarshal replaces the slice with a new empty slice. 267 // 268 // To unmarshal a JSON array into a Go array, Unmarshal decodes 269 // JSON array elements into corresponding Go array elements. 270 // If the Go array is smaller than the JSON array, 271 // the additional JSON array elements are discarded. 272 // If the JSON array is smaller than the Go array, 273 // the additional Go array elements are set to zero values. 274 // 275 // To unmarshal a JSON object into a map, Unmarshal first establishes a map to 276 // use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal 277 // reuses the existing map, keeping existing entries. Unmarshal then stores 278 // key-value pairs from the JSON object into the map. The map's key type must 279 // either be any string type, an integer, implement json.Unmarshaler, or 280 // implement encoding.TextUnmarshaler. 281 // 282 // If a JSON value is not appropriate for a given target type, 283 // or if a JSON number overflows the target type, Unmarshal 284 // skips that field and completes the unmarshaling as best it can. 285 // If no more serious errors are encountered, Unmarshal returns 286 // an UnmarshalTypeError describing the earliest such error. In any 287 // case, it's not guaranteed that all the remaining fields following 288 // the problematic one will be unmarshaled into the target object. 289 // 290 // The JSON null value unmarshals into an interface, map, pointer, or slice 291 // by setting that Go value to nil. Because null is often used in JSON to mean 292 // “not present,” unmarshaling a JSON null into any other Go type has no effect 293 // on the value and produces no error. 294 // 295 // When unmarshaling quoted strings, invalid UTF-8 or 296 // invalid UTF-16 surrogate pairs are not treated as an error. 297 // Instead, they are replaced by the Unicode replacement 298 // character U+FFFD. 299 func Unmarshal(data []byte, v interface{}) (err error) { 300 defer func() { 301 if r := recover(); r != nil { 302 err = json.Unmarshal(data, v) 303 304 return 305 } 306 }() 307 308 err = unmarshal(data, v) 309 if err != nil { 310 err = json.Unmarshal(data, v) 311 } 312 313 return err 314 } 315 316 // UnmarshalContext parses the JSON-encoded data and stores the result 317 // in the value pointed to by v. If you implement the UnmarshalerContext interface, 318 // call it with ctx as an argument. 319 func UnmarshalContext(ctx context.Context, data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error { 320 return unmarshalContext(ctx, data, v) 321 } 322 323 func UnmarshalWithOption(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error { 324 return unmarshal(data, v, optFuncs...) 325 } 326 327 func UnmarshalNoEscape(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error { 328 return unmarshalNoEscape(data, v, optFuncs...) 329 } 330 331 // A Token holds a value of one of these types: 332 // 333 // Delim, for the four JSON delimiters [ ] { } 334 // bool, for JSON booleans 335 // float64, for JSON numbers 336 // Number, for JSON numbers 337 // string, for JSON string literals 338 // nil, for JSON null 339 type Token = json.Token 340 341 // A Number represents a JSON number literal. 342 type Number = json.Number 343 344 // RawMessage is a raw encoded JSON value. 345 // It implements Marshaler and Unmarshaler and can 346 // be used to delay JSON decoding or precompute a JSON encoding. 347 type RawMessage = json.RawMessage 348 349 // A Delim is a JSON array or object delimiter, one of [ ] { or }. 350 type Delim = json.Delim 351 352 // Compact appends to dst the JSON-encoded src with 353 // insignificant space characters elided. 354 func Compact(dst *bytes.Buffer, src []byte) error { 355 return encoder.Compact(dst, src, false) 356 } 357 358 // Indent appends to dst an indented form of the JSON-encoded src. 359 // Each element in a JSON object or array begins on a new, 360 // indented line beginning with prefix followed by one or more 361 // copies of indent according to the indentation nesting. 362 // The data appended to dst does not begin with the prefix nor 363 // any indentation, to make it easier to embed inside other formatted JSON data. 364 // Although leading space characters (space, tab, carriage return, newline) 365 // at the beginning of src are dropped, trailing space characters 366 // at the end of src are preserved and copied to dst. 367 // For example, if src has no trailing spaces, neither will dst; 368 // if src ends in a trailing newline, so will dst. 369 func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error { 370 return encoder.Indent(dst, src, prefix, indent) 371 } 372 373 // HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029 374 // characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029 375 // so that the JSON will be safe to embed inside HTML <script> tags. 376 // For historical reasons, web browsers don't honor standard HTML 377 // escaping within <script> tags, so an alternative JSON encoding must 378 // be used. 379 func HTMLEscape(dst *bytes.Buffer, src []byte) { 380 var v interface{} 381 dec := NewDecoder(bytes.NewBuffer(src)) 382 dec.UseNumber() 383 if err := dec.Decode(&v); err != nil { 384 return 385 } 386 buf, _ := marshal(v) 387 dst.Write(buf) 388 } 389 390 // Valid reports whether data is a valid JSON encoding. 391 func Valid(data []byte) bool { 392 var v interface{} 393 decoder := NewDecoder(bytes.NewReader(data)) 394 err := decoder.Decode(&v) 395 if err != nil { 396 return false 397 } 398 if !decoder.More() { 399 return true 400 } 401 return decoder.InputOffset() >= int64(len(data)) 402 } 403 404 func init() { 405 encoder.Marshal = Marshal 406 encoder.Unmarshal = Unmarshal 407 }