k8s.io/kube-openapi@v0.0.0-20240228011516-70dd3763d340/pkg/internal/third_party/go-json-experiment/json/arshal_test.go (about) 1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package json 6 7 import ( 8 "bytes" 9 "encoding" 10 "encoding/base32" 11 "encoding/base64" 12 "encoding/hex" 13 "errors" 14 "fmt" 15 "io" 16 "math" 17 "net" 18 "path" 19 "reflect" 20 "runtime" 21 "strconv" 22 "strings" 23 "testing" 24 "time" 25 ) 26 27 type testName struct { 28 name string 29 where pc 30 } 31 32 func name(s string) (t testName) { 33 t.name = s 34 runtime.Callers(2, t.where[:]) 35 return t 36 } 37 38 type pc [1]uintptr 39 40 func (pc pc) String() string { 41 frames := runtime.CallersFrames(pc[:]) 42 frame, _ := frames.Next() 43 return fmt.Sprintf("%s:%d", path.Base(frame.File), frame.Line) 44 } 45 46 type ( 47 jsonObject = map[string]any 48 jsonArray = []any 49 50 namedAny any 51 namedBool bool 52 namedString string 53 namedBytes []byte 54 namedInt64 int64 55 namedUint64 uint64 56 namedFloat64 float64 57 namedByte byte 58 59 recursiveMap map[string]recursiveMap 60 recursiveSlice []recursiveSlice 61 recursivePointer struct{ P *recursivePointer } 62 63 structEmpty struct{} 64 structConflicting struct { 65 A string `json:"conflict"` 66 B string `json:"conflict"` 67 } 68 structNoneExported struct { 69 unexported string 70 } 71 structUnexportedIgnored struct { 72 ignored string `json:"-"` 73 } 74 structMalformedTag struct { 75 Malformed string `json:"\""` 76 } 77 structUnexportedTag struct { 78 unexported string `json:"name"` 79 } 80 structUnexportedEmbedded struct { 81 namedString 82 } 83 structIgnoredUnexportedEmbedded struct { 84 namedString `json:"-"` 85 } 86 structWeirdNames struct { 87 Empty string `json:"''"` 88 Comma string `json:"','"` 89 Quote string `json:"'\"'"` 90 } 91 structNoCase struct { 92 AaA string `json:",nocase"` 93 AAa string `json:",nocase"` 94 AAA string 95 } 96 structScalars struct { 97 unexported bool 98 Ignored bool `json:"-"` 99 100 Bool bool 101 String string 102 Bytes []byte 103 Int int64 104 Uint uint64 105 Float float64 106 } 107 structSlices struct { 108 unexported bool 109 Ignored bool `json:"-"` 110 111 SliceBool []bool 112 SliceString []string 113 SliceBytes [][]byte 114 SliceInt []int64 115 SliceUint []uint64 116 SliceFloat []float64 117 } 118 structMaps struct { 119 unexported bool 120 Ignored bool `json:"-"` 121 122 MapBool map[string]bool 123 MapString map[string]string 124 MapBytes map[string][]byte 125 MapInt map[string]int64 126 MapUint map[string]uint64 127 MapFloat map[string]float64 128 } 129 structAll struct { 130 Bool bool 131 String string 132 Bytes []byte 133 Int int64 134 Uint uint64 135 Float float64 136 Map map[string]string 137 StructScalars structScalars 138 StructMaps structMaps 139 StructSlices structSlices 140 Slice []string 141 Array [1]string 142 Pointer *structAll 143 Interface any 144 } 145 structStringifiedAll struct { 146 Bool bool `json:",string"` 147 String string `json:",string"` 148 Bytes []byte `json:",string"` 149 Int int64 `json:",string"` 150 Uint uint64 `json:",string"` 151 Float float64 `json:",string"` 152 Map map[string]string `json:",string"` 153 StructScalars structScalars `json:",string"` 154 StructMaps structMaps `json:",string"` 155 StructSlices structSlices `json:",string"` 156 Slice []string `json:",string"` 157 Array [1]string `json:",string"` 158 Pointer *structStringifiedAll `json:",string"` 159 Interface any `json:",string"` 160 } 161 structOmitZeroAll struct { 162 Bool bool `json:",omitzero"` 163 String string `json:",omitzero"` 164 Bytes []byte `json:",omitzero"` 165 Int int64 `json:",omitzero"` 166 Uint uint64 `json:",omitzero"` 167 Float float64 `json:",omitzero"` 168 Map map[string]string `json:",omitzero"` 169 StructScalars structScalars `json:",omitzero"` 170 StructMaps structMaps `json:",omitzero"` 171 StructSlices structSlices `json:",omitzero"` 172 Slice []string `json:",omitzero"` 173 Array [1]string `json:",omitzero"` 174 Pointer *structOmitZeroAll `json:",omitzero"` 175 Interface any `json:",omitzero"` 176 } 177 structOmitZeroMethodAll struct { 178 ValueAlwaysZero valueAlwaysZero `json:",omitzero"` 179 ValueNeverZero valueNeverZero `json:",omitzero"` 180 PointerAlwaysZero pointerAlwaysZero `json:",omitzero"` 181 PointerNeverZero pointerNeverZero `json:",omitzero"` 182 PointerValueAlwaysZero *valueAlwaysZero `json:",omitzero"` 183 PointerValueNeverZero *valueNeverZero `json:",omitzero"` 184 PointerPointerAlwaysZero *pointerAlwaysZero `json:",omitzero"` 185 PointerPointerNeverZero *pointerNeverZero `json:",omitzero"` 186 PointerPointerValueAlwaysZero **valueAlwaysZero `json:",omitzero"` 187 PointerPointerValueNeverZero **valueNeverZero `json:",omitzero"` 188 PointerPointerPointerAlwaysZero **pointerAlwaysZero `json:",omitzero"` 189 PointerPointerPointerNeverZero **pointerNeverZero `json:",omitzero"` 190 } 191 structOmitZeroMethodInterfaceAll struct { 192 ValueAlwaysZero isZeroer `json:",omitzero"` 193 ValueNeverZero isZeroer `json:",omitzero"` 194 PointerValueAlwaysZero isZeroer `json:",omitzero"` 195 PointerValueNeverZero isZeroer `json:",omitzero"` 196 PointerPointerAlwaysZero isZeroer `json:",omitzero"` 197 PointerPointerNeverZero isZeroer `json:",omitzero"` 198 } 199 structOmitEmptyAll struct { 200 Bool bool `json:",omitempty"` 201 PointerBool *bool `json:",omitempty"` 202 String string `json:",omitempty"` 203 StringEmpty stringMarshalEmpty `json:",omitempty"` 204 StringNonEmpty stringMarshalNonEmpty `json:",omitempty"` 205 PointerString *string `json:",omitempty"` 206 PointerStringEmpty *stringMarshalEmpty `json:",omitempty"` 207 PointerStringNonEmpty *stringMarshalNonEmpty `json:",omitempty"` 208 Bytes []byte `json:",omitempty"` 209 BytesEmpty bytesMarshalEmpty `json:",omitempty"` 210 BytesNonEmpty bytesMarshalNonEmpty `json:",omitempty"` 211 PointerBytes *[]byte `json:",omitempty"` 212 PointerBytesEmpty *bytesMarshalEmpty `json:",omitempty"` 213 PointerBytesNonEmpty *bytesMarshalNonEmpty `json:",omitempty"` 214 Float float64 `json:",omitempty"` 215 PointerFloat *float64 `json:",omitempty"` 216 Map map[string]string `json:",omitempty"` 217 MapEmpty mapMarshalEmpty `json:",omitempty"` 218 MapNonEmpty mapMarshalNonEmpty `json:",omitempty"` 219 PointerMap *map[string]string `json:",omitempty"` 220 PointerMapEmpty *mapMarshalEmpty `json:",omitempty"` 221 PointerMapNonEmpty *mapMarshalNonEmpty `json:",omitempty"` 222 Slice []string `json:",omitempty"` 223 SliceEmpty sliceMarshalEmpty `json:",omitempty"` 224 SliceNonEmpty sliceMarshalNonEmpty `json:",omitempty"` 225 PointerSlice *[]string `json:",omitempty"` 226 PointerSliceEmpty *sliceMarshalEmpty `json:",omitempty"` 227 PointerSliceNonEmpty *sliceMarshalNonEmpty `json:",omitempty"` 228 Pointer *structOmitZeroEmptyAll `json:",omitempty"` 229 Interface any `json:",omitempty"` 230 } 231 structOmitZeroEmptyAll struct { 232 Bool bool `json:",omitzero,omitempty"` 233 String string `json:",omitzero,omitempty"` 234 Bytes []byte `json:",omitzero,omitempty"` 235 Int int64 `json:",omitzero,omitempty"` 236 Uint uint64 `json:",omitzero,omitempty"` 237 Float float64 `json:",omitzero,omitempty"` 238 Map map[string]string `json:",omitzero,omitempty"` 239 Slice []string `json:",omitzero,omitempty"` 240 Array [1]string `json:",omitzero,omitempty"` 241 Pointer *structOmitZeroEmptyAll `json:",omitzero,omitempty"` 242 Interface any `json:",omitzero,omitempty"` 243 } 244 structFormatBytes struct { 245 Base16 []byte `json:",format:base16"` 246 Base32 []byte `json:",format:base32"` 247 Base32Hex []byte `json:",format:base32hex"` 248 Base64 []byte `json:",format:base64"` 249 Base64URL []byte `json:",format:base64url"` 250 Array []byte `json:",format:array"` 251 } 252 structFormatFloats struct { 253 NonFinite float64 `json:",format:nonfinite"` 254 PointerNonFinite *float64 `json:",format:nonfinite"` 255 } 256 structFormatMaps struct { 257 EmitNull map[string]string `json:",format:emitnull"` 258 PointerEmitNull *map[string]string `json:",format:emitnull"` 259 } 260 structFormatSlices struct { 261 EmitNull []string `json:",format:emitnull"` 262 PointerEmitNull *[]string `json:",format:emitnull"` 263 } 264 structFormatInvalid struct { 265 Bool bool `json:",omitzero,format:invalid"` 266 String string `json:",omitzero,format:invalid"` 267 Bytes []byte `json:",omitzero,format:invalid"` 268 Int int64 `json:",omitzero,format:invalid"` 269 Uint uint64 `json:",omitzero,format:invalid"` 270 Float float64 `json:",omitzero,format:invalid"` 271 Map map[string]string `json:",omitzero,format:invalid"` 272 Struct structAll `json:",omitzero,format:invalid"` 273 Slice []string `json:",omitzero,format:invalid"` 274 Array [1]string `json:",omitzero,format:invalid"` 275 Interface any `json:",omitzero,format:invalid"` 276 } 277 structTimeFormat struct { 278 T1 time.Time 279 T2 time.Time `json:",format:ANSIC"` 280 T3 time.Time `json:",format:UnixDate"` 281 T4 time.Time `json:",format:RubyDate"` 282 T5 time.Time `json:",format:RFC822"` 283 T6 time.Time `json:",format:RFC822Z"` 284 T7 time.Time `json:",format:RFC850"` 285 T8 time.Time `json:",format:RFC1123"` 286 T9 time.Time `json:",format:RFC1123Z"` 287 T10 time.Time `json:",format:RFC3339"` 288 T11 time.Time `json:",format:RFC3339Nano"` 289 T12 time.Time `json:",format:Kitchen"` 290 T13 time.Time `json:",format:Stamp"` 291 T14 time.Time `json:",format:StampMilli"` 292 T15 time.Time `json:",format:StampMicro"` 293 T16 time.Time `json:",format:StampNano"` 294 T17 time.Time `json:",format:'2006-01-02'"` 295 T18 time.Time `json:",format:'\"weird\"2006'"` 296 } 297 structInlined struct { 298 X structInlinedL1 `json:",inline"` 299 *StructEmbed2 // implicit inline 300 } 301 structInlinedL1 struct { 302 X *structInlinedL2 `json:",inline"` 303 StructEmbed1 `json:",inline"` 304 } 305 structInlinedL2 struct{ A, B, C string } 306 StructEmbed1 struct{ C, D, E string } 307 StructEmbed2 struct{ E, F, G string } 308 structUnknownRawValue struct { 309 A int `json:",omitzero"` 310 X RawValue `json:",unknown"` 311 B int `json:",omitzero"` 312 } 313 structInlineRawValue struct { 314 A int `json:",omitzero"` 315 X RawValue `json:",inline"` 316 B int `json:",omitzero"` 317 } 318 structInlinePointerRawValue struct { 319 A int `json:",omitzero"` 320 X *RawValue `json:",inline"` 321 B int `json:",omitzero"` 322 } 323 structInlinePointerInlineRawValue struct { 324 X *struct { 325 A int 326 X RawValue `json:",inline"` 327 } `json:",inline"` 328 } 329 structInlineInlinePointerRawValue struct { 330 X struct { 331 X *RawValue `json:",inline"` 332 } `json:",inline"` 333 } 334 structInlineMapStringAny struct { 335 A int `json:",omitzero"` 336 X jsonObject `json:",inline"` 337 B int `json:",omitzero"` 338 } 339 structInlinePointerMapStringAny struct { 340 A int `json:",omitzero"` 341 X *jsonObject `json:",inline"` 342 B int `json:",omitzero"` 343 } 344 structInlinePointerInlineMapStringAny struct { 345 X *struct { 346 A int 347 X jsonObject `json:",inline"` 348 } `json:",inline"` 349 } 350 structInlineInlinePointerMapStringAny struct { 351 X struct { 352 X *jsonObject `json:",inline"` 353 } `json:",inline"` 354 } 355 structInlineMapStringInt struct { 356 X map[string]int `json:",inline"` 357 } 358 structNoCaseInlineRawValue struct { 359 AAA string `json:",omitempty"` 360 AaA string `json:",omitempty,nocase"` 361 AAa string `json:",omitempty,nocase"` 362 Aaa string `json:",omitempty"` 363 X RawValue `json:",inline"` 364 } 365 structNoCaseInlineMapStringAny struct { 366 AAA string `json:",omitempty"` 367 AaA string `json:",omitempty,nocase"` 368 AAa string `json:",omitempty,nocase"` 369 Aaa string `json:",omitempty"` 370 X jsonObject `json:",inline"` 371 } 372 373 allMethods struct { 374 method string // the method that was called 375 value []byte // the raw value to provide or store 376 } 377 allMethodsExceptJSONv2 struct { 378 allMethods 379 MarshalNextJSON struct{} // cancel out MarshalNextJSON method with collision 380 UnmarshalNextJSON struct{} // cancel out UnmarshalNextJSON method with collision 381 } 382 allMethodsExceptJSONv1 struct { 383 allMethods 384 MarshalJSON struct{} // cancel out MarshalJSON method with collision 385 UnmarshalJSON struct{} // cancel out UnmarshalJSON method with collision 386 } 387 allMethodsExceptText struct { 388 allMethods 389 MarshalText struct{} // cancel out MarshalText method with collision 390 UnmarshalText struct{} // cancel out UnmarshalText method with collision 391 } 392 onlyMethodJSONv2 struct { 393 allMethods 394 MarshalJSON struct{} // cancel out MarshalJSON method with collision 395 UnmarshalJSON struct{} // cancel out UnmarshalJSON method with collision 396 MarshalText struct{} // cancel out MarshalText method with collision 397 UnmarshalText struct{} // cancel out UnmarshalText method with collision 398 } 399 onlyMethodJSONv1 struct { 400 allMethods 401 MarshalNextJSON struct{} // cancel out MarshalNextJSON method with collision 402 UnmarshalNextJSON struct{} // cancel out UnmarshalNextJSON method with collision 403 MarshalText struct{} // cancel out MarshalText method with collision 404 UnmarshalText struct{} // cancel out UnmarshalText method with collision 405 } 406 onlyMethodText struct { 407 allMethods 408 MarshalNextJSON struct{} // cancel out MarshalNextJSON method with collision 409 UnmarshalNextJSON struct{} // cancel out UnmarshalNextJSON method with collision 410 MarshalJSON struct{} // cancel out MarshalJSON method with collision 411 UnmarshalJSON struct{} // cancel out UnmarshalJSON method with collision 412 } 413 414 structMethodJSONv2 struct{ value string } 415 structMethodJSONv1 struct{ value string } 416 structMethodText struct{ value string } 417 418 marshalJSONv2Func func(MarshalOptions, *Encoder) error 419 marshalJSONv1Func func() ([]byte, error) 420 marshalTextFunc func() ([]byte, error) 421 unmarshalJSONv2Func func(UnmarshalOptions, *Decoder) error 422 unmarshalJSONv1Func func([]byte) error 423 unmarshalTextFunc func([]byte) error 424 425 nocaseString string 426 427 stringMarshalEmpty string 428 stringMarshalNonEmpty string 429 bytesMarshalEmpty []byte 430 bytesMarshalNonEmpty []byte 431 mapMarshalEmpty map[string]string 432 mapMarshalNonEmpty map[string]string 433 sliceMarshalEmpty []string 434 sliceMarshalNonEmpty []string 435 436 valueAlwaysZero string 437 valueNeverZero string 438 pointerAlwaysZero string 439 pointerNeverZero string 440 441 valueStringer struct{} 442 pointerStringer struct{} 443 444 cyclicA struct { 445 B1 cyclicB `json:",inline"` 446 B2 cyclicB `json:",inline"` 447 } 448 cyclicB struct { 449 F int 450 A *cyclicA `json:",inline"` 451 } 452 ) 453 454 func (p *allMethods) MarshalNextJSON(mo MarshalOptions, enc *Encoder) error { 455 if got, want := "MarshalNextJSON", p.method; got != want { 456 return fmt.Errorf("called wrong method: got %v, want %v", got, want) 457 } 458 return enc.WriteValue(p.value) 459 } 460 func (p *allMethods) MarshalJSON() ([]byte, error) { 461 if got, want := "MarshalJSON", p.method; got != want { 462 return nil, fmt.Errorf("called wrong method: got %v, want %v", got, want) 463 } 464 return p.value, nil 465 } 466 func (p *allMethods) MarshalText() ([]byte, error) { 467 if got, want := "MarshalText", p.method; got != want { 468 return nil, fmt.Errorf("called wrong method: got %v, want %v", got, want) 469 } 470 return p.value, nil 471 } 472 473 func (p *allMethods) UnmarshalNextJSON(uo UnmarshalOptions, dec *Decoder) error { 474 p.method = "UnmarshalNextJSON" 475 val, err := dec.ReadValue() 476 p.value = val 477 return err 478 } 479 func (p *allMethods) UnmarshalJSON(val []byte) error { 480 p.method = "UnmarshalJSON" 481 p.value = val 482 return nil 483 } 484 func (p *allMethods) UnmarshalText(val []byte) error { 485 p.method = "UnmarshalText" 486 p.value = val 487 return nil 488 } 489 490 func (s structMethodJSONv2) MarshalNextJSON(mo MarshalOptions, enc *Encoder) error { 491 return enc.WriteToken(String(s.value)) 492 } 493 func (s *structMethodJSONv2) UnmarshalNextJSON(uo UnmarshalOptions, dec *Decoder) error { 494 tok, err := dec.ReadToken() 495 if err != nil { 496 return err 497 } 498 if k := tok.Kind(); k != '"' { 499 return &SemanticError{action: "unmarshal", JSONKind: k, GoType: structMethodJSONv2Type} 500 } 501 s.value = tok.String() 502 return nil 503 } 504 505 func (s structMethodJSONv1) MarshalJSON() ([]byte, error) { 506 return appendString(nil, s.value, false, nil) 507 } 508 func (s *structMethodJSONv1) UnmarshalJSON(b []byte) error { 509 if k := RawValue(b).Kind(); k != '"' { 510 return &SemanticError{action: "unmarshal", JSONKind: k, GoType: structMethodJSONv1Type} 511 } 512 b, _ = unescapeString(nil, b) 513 s.value = string(b) 514 return nil 515 } 516 517 func (s structMethodText) MarshalText() ([]byte, error) { 518 return []byte(s.value), nil 519 } 520 func (s *structMethodText) UnmarshalText(b []byte) error { 521 s.value = string(b) 522 return nil 523 } 524 525 func (f marshalJSONv2Func) MarshalNextJSON(mo MarshalOptions, enc *Encoder) error { 526 return f(mo, enc) 527 } 528 func (f marshalJSONv1Func) MarshalJSON() ([]byte, error) { 529 return f() 530 } 531 func (f marshalTextFunc) MarshalText() ([]byte, error) { 532 return f() 533 } 534 func (f unmarshalJSONv2Func) UnmarshalNextJSON(uo UnmarshalOptions, dec *Decoder) error { 535 return f(uo, dec) 536 } 537 func (f unmarshalJSONv1Func) UnmarshalJSON(b []byte) error { 538 return f(b) 539 } 540 func (f unmarshalTextFunc) UnmarshalText(b []byte) error { 541 return f(b) 542 } 543 544 func (k nocaseString) MarshalText() ([]byte, error) { 545 return []byte(strings.ToLower(string(k))), nil 546 } 547 func (k *nocaseString) UnmarshalText(b []byte) error { 548 *k = nocaseString(strings.ToLower(string(b))) 549 return nil 550 } 551 552 func (stringMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`""`), nil } 553 func (stringMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`"value"`), nil } 554 func (bytesMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`[]`), nil } 555 func (bytesMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`["value"]`), nil } 556 func (mapMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`{}`), nil } 557 func (mapMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`{"key":"value"}`), nil } 558 func (sliceMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`[]`), nil } 559 func (sliceMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`["value"]`), nil } 560 561 func (valueAlwaysZero) IsZero() bool { return true } 562 func (valueNeverZero) IsZero() bool { return false } 563 func (*pointerAlwaysZero) IsZero() bool { return true } 564 func (*pointerNeverZero) IsZero() bool { return false } 565 566 func (valueStringer) String() string { return "" } 567 func (*pointerStringer) String() string { return "" } 568 569 var ( 570 namedBoolType = reflect.TypeOf((*namedBool)(nil)).Elem() 571 intType = reflect.TypeOf((*int)(nil)).Elem() 572 int8Type = reflect.TypeOf((*int8)(nil)).Elem() 573 int16Type = reflect.TypeOf((*int16)(nil)).Elem() 574 int32Type = reflect.TypeOf((*int32)(nil)).Elem() 575 int64Type = reflect.TypeOf((*int64)(nil)).Elem() 576 uintType = reflect.TypeOf((*uint)(nil)).Elem() 577 uint8Type = reflect.TypeOf((*uint8)(nil)).Elem() 578 uint16Type = reflect.TypeOf((*uint16)(nil)).Elem() 579 uint32Type = reflect.TypeOf((*uint32)(nil)).Elem() 580 uint64Type = reflect.TypeOf((*uint64)(nil)).Elem() 581 sliceStringType = reflect.TypeOf((*[]string)(nil)).Elem() 582 array1StringType = reflect.TypeOf((*[1]string)(nil)).Elem() 583 array0ByteType = reflect.TypeOf((*[0]byte)(nil)).Elem() 584 array1ByteType = reflect.TypeOf((*[1]byte)(nil)).Elem() 585 array2ByteType = reflect.TypeOf((*[2]byte)(nil)).Elem() 586 array3ByteType = reflect.TypeOf((*[3]byte)(nil)).Elem() 587 array4ByteType = reflect.TypeOf((*[4]byte)(nil)).Elem() 588 mapStringStringType = reflect.TypeOf((*map[string]string)(nil)).Elem() 589 structAllType = reflect.TypeOf((*structAll)(nil)).Elem() 590 structConflictingType = reflect.TypeOf((*structConflicting)(nil)).Elem() 591 structNoneExportedType = reflect.TypeOf((*structNoneExported)(nil)).Elem() 592 structMalformedTagType = reflect.TypeOf((*structMalformedTag)(nil)).Elem() 593 structUnexportedTagType = reflect.TypeOf((*structUnexportedTag)(nil)).Elem() 594 structUnexportedEmbeddedType = reflect.TypeOf((*structUnexportedEmbedded)(nil)).Elem() 595 structUnknownRawValueType = reflect.TypeOf((*structUnknownRawValue)(nil)).Elem() 596 allMethodsType = reflect.TypeOf((*allMethods)(nil)).Elem() 597 allMethodsExceptJSONv2Type = reflect.TypeOf((*allMethodsExceptJSONv2)(nil)).Elem() 598 allMethodsExceptJSONv1Type = reflect.TypeOf((*allMethodsExceptJSONv1)(nil)).Elem() 599 allMethodsExceptTextType = reflect.TypeOf((*allMethodsExceptText)(nil)).Elem() 600 onlyMethodJSONv2Type = reflect.TypeOf((*onlyMethodJSONv2)(nil)).Elem() 601 onlyMethodJSONv1Type = reflect.TypeOf((*onlyMethodJSONv1)(nil)).Elem() 602 onlyMethodTextType = reflect.TypeOf((*onlyMethodText)(nil)).Elem() 603 structMethodJSONv2Type = reflect.TypeOf((*structMethodJSONv2)(nil)).Elem() 604 structMethodJSONv1Type = reflect.TypeOf((*structMethodJSONv1)(nil)).Elem() 605 structMethodTextType = reflect.TypeOf((*structMethodText)(nil)).Elem() 606 marshalJSONv2FuncType = reflect.TypeOf((*marshalJSONv2Func)(nil)).Elem() 607 marshalJSONv1FuncType = reflect.TypeOf((*marshalJSONv1Func)(nil)).Elem() 608 marshalTextFuncType = reflect.TypeOf((*marshalTextFunc)(nil)).Elem() 609 unmarshalJSONv2FuncType = reflect.TypeOf((*unmarshalJSONv2Func)(nil)).Elem() 610 unmarshalJSONv1FuncType = reflect.TypeOf((*unmarshalJSONv1Func)(nil)).Elem() 611 unmarshalTextFuncType = reflect.TypeOf((*unmarshalTextFunc)(nil)).Elem() 612 nocaseStringType = reflect.TypeOf((*nocaseString)(nil)).Elem() 613 ioReaderType = reflect.TypeOf((*io.Reader)(nil)).Elem() 614 fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() 615 chanStringType = reflect.TypeOf((*chan string)(nil)).Elem() 616 ) 617 618 func addr[T any](v T) *T { 619 return &v 620 } 621 622 func mustParseTime(layout, value string) time.Time { 623 t, err := time.Parse(layout, value) 624 if err != nil { 625 panic(err) 626 } 627 return t 628 } 629 630 func TestMarshal(t *testing.T) { 631 tests := []struct { 632 name testName 633 mopts MarshalOptions 634 eopts EncodeOptions 635 in any 636 want string 637 wantErr error 638 639 canonicalize bool // canonicalize the output before comparing? 640 useWriter bool // call MarshalFull instead of Marshal 641 }{{ 642 name: name("Nil"), 643 in: nil, 644 want: `null`, 645 }, { 646 name: name("Bools"), 647 in: []bool{false, true}, 648 want: `[false,true]`, 649 }, { 650 name: name("Bools/Named"), 651 in: []namedBool{false, true}, 652 want: `[false,true]`, 653 }, { 654 name: name("Bools/NotStringified"), 655 mopts: MarshalOptions{StringifyNumbers: true}, 656 in: []bool{false, true}, 657 want: `[false,true]`, 658 }, { 659 name: name("Bools/IgnoreInvalidFormat"), 660 mopts: MarshalOptions{formatDepth: 1000, format: "invalid"}, 661 in: true, 662 want: `true`, 663 }, { 664 name: name("Strings"), 665 in: []string{"", "hello", "世界"}, 666 want: `["","hello","世界"]`, 667 }, { 668 name: name("Strings/Named"), 669 in: []namedString{"", "hello", "世界"}, 670 want: `["","hello","世界"]`, 671 }, { 672 name: name("Strings/IgnoreInvalidFormat"), 673 mopts: MarshalOptions{formatDepth: 1000, format: "invalid"}, 674 in: "string", 675 want: `"string"`, 676 }, { 677 name: name("Bytes"), 678 in: [][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}, 679 want: `["","","AQ==","AQI=","AQID"]`, 680 }, { 681 name: name("Bytes/Large"), 682 in: []byte("the quick brown fox jumped over the lazy dog and ate the homework that I spent so much time on."), 683 want: `"dGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cgYW5kIGF0ZSB0aGUgaG9tZXdvcmsgdGhhdCBJIHNwZW50IHNvIG11Y2ggdGltZSBvbi4="`, 684 }, { 685 name: name("Bytes/Named"), 686 in: []namedBytes{nil, {}, {1}, {1, 2}, {1, 2, 3}}, 687 want: `["","","AQ==","AQI=","AQID"]`, 688 }, { 689 name: name("Bytes/NotStringified"), 690 mopts: MarshalOptions{StringifyNumbers: true}, 691 in: [][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}, 692 want: `["","","AQ==","AQI=","AQID"]`, 693 }, { 694 // NOTE: []namedByte is not assignable to []byte, 695 // so the following should be treated as a slice of uints. 696 name: name("Bytes/Invariant"), 697 in: [][]namedByte{nil, {}, {1}, {1, 2}, {1, 2, 3}}, 698 want: `[[],[],[1],[1,2],[1,2,3]]`, 699 }, { 700 // NOTE: This differs in behavior from v1, 701 // but keeps the representation of slices and arrays more consistent. 702 name: name("Bytes/ByteArray"), 703 in: [5]byte{'h', 'e', 'l', 'l', 'o'}, 704 want: `"aGVsbG8="`, 705 }, { 706 // NOTE: []namedByte is not assignable to []byte, 707 // so the following should be treated as an array of uints. 708 name: name("Bytes/NamedByteArray"), 709 in: [5]namedByte{'h', 'e', 'l', 'l', 'o'}, 710 want: `[104,101,108,108,111]`, 711 }, { 712 name: name("Bytes/IgnoreInvalidFormat"), 713 mopts: MarshalOptions{formatDepth: 1000, format: "invalid"}, 714 in: []byte("hello"), 715 want: `"aGVsbG8="`, 716 }, { 717 name: name("Ints"), 718 in: []any{ 719 int(0), int8(math.MinInt8), int16(math.MinInt16), int32(math.MinInt32), int64(math.MinInt64), namedInt64(-6464), 720 }, 721 want: `[0,-128,-32768,-2147483648,-9223372036854775808,-6464]`, 722 }, { 723 name: name("Ints/Stringified"), 724 mopts: MarshalOptions{StringifyNumbers: true}, 725 in: []any{ 726 int(0), int8(math.MinInt8), int16(math.MinInt16), int32(math.MinInt32), int64(math.MinInt64), namedInt64(-6464), 727 }, 728 want: `["0","-128","-32768","-2147483648","-9223372036854775808","-6464"]`, 729 }, { 730 name: name("Ints/IgnoreInvalidFormat"), 731 mopts: MarshalOptions{formatDepth: 1000, format: "invalid"}, 732 in: int(0), 733 want: `0`, 734 }, { 735 name: name("Uints"), 736 in: []any{ 737 uint(0), uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64), namedUint64(6464), 738 }, 739 want: `[0,255,65535,4294967295,18446744073709551615,6464]`, 740 }, { 741 name: name("Uints/Stringified"), 742 mopts: MarshalOptions{StringifyNumbers: true}, 743 in: []any{ 744 uint(0), uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64), namedUint64(6464), 745 }, 746 want: `["0","255","65535","4294967295","18446744073709551615","6464"]`, 747 }, { 748 name: name("Uints/IgnoreInvalidFormat"), 749 mopts: MarshalOptions{formatDepth: 1000, format: "invalid"}, 750 in: uint(0), 751 want: `0`, 752 }, { 753 name: name("Floats"), 754 in: []any{ 755 float32(math.MaxFloat32), float64(math.MaxFloat64), namedFloat64(64.64), 756 }, 757 want: `[3.4028235e+38,1.7976931348623157e+308,64.64]`, 758 }, { 759 name: name("Floats/Stringified"), 760 mopts: MarshalOptions{StringifyNumbers: true}, 761 in: []any{ 762 float32(math.MaxFloat32), float64(math.MaxFloat64), namedFloat64(64.64), 763 }, 764 want: `["3.4028235e+38","1.7976931348623157e+308","64.64"]`, 765 }, { 766 name: name("Floats/Invalid/NaN"), 767 mopts: MarshalOptions{StringifyNumbers: true}, 768 in: math.NaN(), 769 wantErr: &SemanticError{action: "marshal", GoType: float64Type, Err: fmt.Errorf("invalid value: %v", math.NaN())}, 770 }, { 771 name: name("Floats/Invalid/PositiveInfinity"), 772 in: math.Inf(+1), 773 wantErr: &SemanticError{action: "marshal", GoType: float64Type, Err: fmt.Errorf("invalid value: %v", math.Inf(+1))}, 774 }, { 775 name: name("Floats/Invalid/NegativeInfinity"), 776 in: math.Inf(-1), 777 wantErr: &SemanticError{action: "marshal", GoType: float64Type, Err: fmt.Errorf("invalid value: %v", math.Inf(-1))}, 778 }, { 779 name: name("Floats/IgnoreInvalidFormat"), 780 mopts: MarshalOptions{formatDepth: 1000, format: "invalid"}, 781 in: float64(0), 782 want: `0`, 783 }, { 784 name: name("Maps/InvalidKey/Bool"), 785 in: map[bool]string{false: "value"}, 786 want: `{`, 787 wantErr: errMissingName, 788 }, { 789 name: name("Maps/InvalidKey/NamedBool"), 790 in: map[namedBool]string{false: "value"}, 791 want: `{`, 792 wantErr: errMissingName, 793 }, { 794 name: name("Maps/InvalidKey/Array"), 795 in: map[[1]string]string{{"key"}: "value"}, 796 want: `{`, 797 wantErr: errMissingName, 798 }, { 799 name: name("Maps/InvalidKey/Channel"), 800 in: map[chan string]string{make(chan string): "value"}, 801 want: `{`, 802 wantErr: &SemanticError{action: "marshal", GoType: chanStringType}, 803 }, { 804 name: name("Maps/ValidKey/Int"), 805 in: map[int64]string{math.MinInt64: "MinInt64", 0: "Zero", math.MaxInt64: "MaxInt64"}, 806 canonicalize: true, 807 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`, 808 }, { 809 name: name("Maps/ValidKey/NamedInt"), 810 in: map[namedInt64]string{math.MinInt64: "MinInt64", 0: "Zero", math.MaxInt64: "MaxInt64"}, 811 canonicalize: true, 812 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`, 813 }, { 814 name: name("Maps/ValidKey/Uint"), 815 in: map[uint64]string{0: "Zero", math.MaxUint64: "MaxUint64"}, 816 canonicalize: true, 817 want: `{"0":"Zero","18446744073709551615":"MaxUint64"}`, 818 }, { 819 name: name("Maps/ValidKey/NamedUint"), 820 in: map[namedUint64]string{0: "Zero", math.MaxUint64: "MaxUint64"}, 821 canonicalize: true, 822 want: `{"0":"Zero","18446744073709551615":"MaxUint64"}`, 823 }, { 824 name: name("Maps/ValidKey/Float"), 825 in: map[float64]string{3.14159: "value"}, 826 want: `{"3.14159":"value"}`, 827 }, { 828 name: name("Maps/InvalidKey/Float/NaN"), 829 in: map[float64]string{math.NaN(): "NaN", math.NaN(): "NaN"}, 830 want: `{`, 831 wantErr: &SemanticError{action: "marshal", GoType: float64Type, Err: errors.New("invalid value: NaN")}, 832 }, { 833 name: name("Maps/ValidKey/Interface"), 834 in: map[any]any{ 835 "key": "key", 836 namedInt64(-64): int32(-32), 837 namedUint64(+64): uint32(+32), 838 namedFloat64(64.64): float32(32.32), 839 }, 840 canonicalize: true, 841 want: `{"-64":-32,"64":32,"64.64":32.32,"key":"key"}`, 842 }, { 843 name: name("Maps/DuplicateName/String/AllowInvalidUTF8+AllowDuplicateNames"), 844 eopts: EncodeOptions{AllowInvalidUTF8: true, AllowDuplicateNames: true}, 845 in: map[string]string{"\x80": "", "\x81": ""}, 846 want: `{"�":"","�":""}`, 847 }, { 848 name: name("Maps/DuplicateName/String/AllowInvalidUTF8"), 849 eopts: EncodeOptions{AllowInvalidUTF8: true}, 850 in: map[string]string{"\x80": "", "\x81": ""}, 851 want: `{"�":""`, 852 wantErr: &SyntacticError{str: `duplicate name "�" in object`}, 853 }, { 854 name: name("Maps/DuplicateName/NoCaseString/AllowDuplicateNames"), 855 eopts: EncodeOptions{AllowDuplicateNames: true}, 856 in: map[nocaseString]string{"hello": "", "HELLO": ""}, 857 want: `{"hello":"","hello":""}`, 858 }, { 859 name: name("Maps/DuplicateName/NoCaseString"), 860 in: map[nocaseString]string{"hello": "", "HELLO": ""}, 861 want: `{"hello":""`, 862 wantErr: &SemanticError{action: "marshal", JSONKind: '"', GoType: reflect.TypeOf(nocaseString("")), Err: &SyntacticError{str: `duplicate name "hello" in object`}}, 863 }, { 864 name: name("Maps/InvalidValue/Channel"), 865 in: map[string]chan string{ 866 "key": nil, 867 }, 868 want: `{"key"`, 869 wantErr: &SemanticError{action: "marshal", GoType: chanStringType}, 870 }, { 871 name: name("Maps/String/Deterministic"), 872 mopts: MarshalOptions{Deterministic: true}, 873 in: map[string]int{"a": 0, "b": 1, "c": 2}, 874 want: `{"a":0,"b":1,"c":2}`, 875 }, { 876 name: name("Maps/String/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"), 877 mopts: MarshalOptions{Deterministic: true}, 878 eopts: EncodeOptions{AllowInvalidUTF8: true, AllowDuplicateNames: false}, 879 in: map[string]int{"\xff": 0, "\xfe": 1}, 880 want: `{"�":1`, 881 wantErr: &SyntacticError{str: `duplicate name "�" in object`}, 882 }, { 883 name: name("Maps/String/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"), 884 mopts: MarshalOptions{Deterministic: true}, 885 eopts: EncodeOptions{AllowInvalidUTF8: true, AllowDuplicateNames: true}, 886 in: map[string]int{"\xff": 0, "\xfe": 1}, 887 want: `{"�":1,"�":0}`, 888 }, { 889 name: name("Maps/String/Deterministic+MarshalFuncs"), 890 mopts: MarshalOptions{ 891 Deterministic: true, 892 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v string) error { 893 if p := enc.StackPointer(); p != "/X" { 894 return fmt.Errorf("invalid stack pointer: got %s, want /X", p) 895 } 896 switch v { 897 case "a": 898 return enc.WriteToken(String("b")) 899 case "b": 900 return enc.WriteToken(String("a")) 901 default: 902 return fmt.Errorf("invalid value: %q", v) 903 } 904 }), 905 }, 906 in: map[namedString]map[string]int{"X": {"a": -1, "b": 1}}, 907 want: `{"X":{"a":1,"b":-1}}`, 908 }, { 909 name: name("Maps/String/Deterministic+MarshalFuncs+RejectDuplicateNames"), 910 mopts: MarshalOptions{ 911 Deterministic: true, 912 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v string) error { 913 if p := enc.StackPointer(); p != "/X" { 914 return fmt.Errorf("invalid stack pointer: got %s, want /X", p) 915 } 916 switch v { 917 case "a", "b": 918 return enc.WriteToken(String("x")) 919 default: 920 return fmt.Errorf("invalid value: %q", v) 921 } 922 }), 923 }, 924 eopts: EncodeOptions{AllowDuplicateNames: false}, 925 in: map[namedString]map[string]int{"X": {"a": 1, "b": 1}}, 926 want: `{"X":{"x":1`, 927 wantErr: &SyntacticError{str: `duplicate name "x" in object`}, 928 }, { 929 name: name("Maps/String/Deterministic+MarshalFuncs+AllowDuplicateNames"), 930 mopts: MarshalOptions{ 931 Deterministic: true, 932 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v string) error { 933 if p := enc.StackPointer(); p != "/0" { 934 return fmt.Errorf("invalid stack pointer: got %s, want /0", p) 935 } 936 switch v { 937 case "a", "b": 938 return enc.WriteToken(String("x")) 939 default: 940 return fmt.Errorf("invalid value: %q", v) 941 } 942 }), 943 }, 944 eopts: EncodeOptions{AllowDuplicateNames: true}, 945 in: map[namedString]map[string]int{"X": {"a": 1, "b": 1}}, 946 // NOTE: Since the names are identical, the exact values may be 947 // non-deterministic since sort cannot distinguish between members. 948 want: `{"X":{"x":1,"x":1}}`, 949 }, { 950 name: name("Maps/RecursiveMap"), 951 in: recursiveMap{ 952 "fizz": { 953 "foo": {}, 954 "bar": nil, 955 }, 956 "buzz": nil, 957 }, 958 canonicalize: true, 959 want: `{"buzz":{},"fizz":{"bar":{},"foo":{}}}`, 960 }, { 961 name: name("Maps/CyclicMap"), 962 in: func() recursiveMap { 963 m := recursiveMap{"k": nil} 964 m["k"] = m 965 return m 966 }(), 967 want: strings.Repeat(`{"k":`, startDetectingCyclesAfter) + `{"k"`, 968 wantErr: &SemanticError{action: "marshal", GoType: reflect.TypeOf(recursiveMap{}), Err: errors.New("encountered a cycle")}, 969 }, { 970 name: name("Maps/IgnoreInvalidFormat"), 971 mopts: MarshalOptions{formatDepth: 1000, format: "invalid"}, 972 in: map[string]string{}, 973 want: `{}`, 974 }, { 975 name: name("Structs/Empty"), 976 in: structEmpty{}, 977 want: `{}`, 978 }, { 979 name: name("Structs/UnexportedIgnored"), 980 in: structUnexportedIgnored{ignored: "ignored"}, 981 want: `{}`, 982 }, { 983 name: name("Structs/IgnoredUnexportedEmbedded"), 984 in: structIgnoredUnexportedEmbedded{namedString: "ignored"}, 985 want: `{}`, 986 }, { 987 name: name("Structs/WeirdNames"), 988 in: structWeirdNames{Empty: "empty", Comma: "comma", Quote: "quote"}, 989 want: `{"":"empty",",":"comma","\"":"quote"}`, 990 }, { 991 name: name("Structs/EscapedNames"), 992 eopts: EncodeOptions{EscapeRune: func(rune) bool { return true }}, 993 in: structWeirdNames{Empty: "empty", Comma: "comma", Quote: "quote"}, 994 want: `{"":"\u0065\u006d\u0070\u0074\u0079","\u002c":"\u0063\u006f\u006d\u006d\u0061","\u0022":"\u0071\u0075\u006f\u0074\u0065"}`, 995 }, { 996 name: name("Structs/NoCase"), 997 in: structNoCase{AaA: "AaA", AAa: "AAa", AAA: "AAA"}, 998 want: `{"AaA":"AaA","AAa":"AAa","AAA":"AAA"}`, 999 }, { 1000 name: name("Structs/Normal"), 1001 eopts: EncodeOptions{Indent: "\t"}, 1002 in: structAll{ 1003 Bool: true, 1004 String: "hello", 1005 Bytes: []byte{1, 2, 3}, 1006 Int: -64, 1007 Uint: +64, 1008 Float: 3.14159, 1009 Map: map[string]string{"key": "value"}, 1010 StructScalars: structScalars{ 1011 Bool: true, 1012 String: "hello", 1013 Bytes: []byte{1, 2, 3}, 1014 Int: -64, 1015 Uint: +64, 1016 Float: 3.14159, 1017 }, 1018 StructMaps: structMaps{ 1019 MapBool: map[string]bool{"": true}, 1020 MapString: map[string]string{"": "hello"}, 1021 MapBytes: map[string][]byte{"": {1, 2, 3}}, 1022 MapInt: map[string]int64{"": -64}, 1023 MapUint: map[string]uint64{"": +64}, 1024 MapFloat: map[string]float64{"": 3.14159}, 1025 }, 1026 StructSlices: structSlices{ 1027 SliceBool: []bool{true}, 1028 SliceString: []string{"hello"}, 1029 SliceBytes: [][]byte{{1, 2, 3}}, 1030 SliceInt: []int64{-64}, 1031 SliceUint: []uint64{+64}, 1032 SliceFloat: []float64{3.14159}, 1033 }, 1034 Slice: []string{"fizz", "buzz"}, 1035 Array: [1]string{"goodbye"}, 1036 Pointer: new(structAll), 1037 Interface: (*structAll)(nil), 1038 }, 1039 want: `{ 1040 "Bool": true, 1041 "String": "hello", 1042 "Bytes": "AQID", 1043 "Int": -64, 1044 "Uint": 64, 1045 "Float": 3.14159, 1046 "Map": { 1047 "key": "value" 1048 }, 1049 "StructScalars": { 1050 "Bool": true, 1051 "String": "hello", 1052 "Bytes": "AQID", 1053 "Int": -64, 1054 "Uint": 64, 1055 "Float": 3.14159 1056 }, 1057 "StructMaps": { 1058 "MapBool": { 1059 "": true 1060 }, 1061 "MapString": { 1062 "": "hello" 1063 }, 1064 "MapBytes": { 1065 "": "AQID" 1066 }, 1067 "MapInt": { 1068 "": -64 1069 }, 1070 "MapUint": { 1071 "": 64 1072 }, 1073 "MapFloat": { 1074 "": 3.14159 1075 } 1076 }, 1077 "StructSlices": { 1078 "SliceBool": [ 1079 true 1080 ], 1081 "SliceString": [ 1082 "hello" 1083 ], 1084 "SliceBytes": [ 1085 "AQID" 1086 ], 1087 "SliceInt": [ 1088 -64 1089 ], 1090 "SliceUint": [ 1091 64 1092 ], 1093 "SliceFloat": [ 1094 3.14159 1095 ] 1096 }, 1097 "Slice": [ 1098 "fizz", 1099 "buzz" 1100 ], 1101 "Array": [ 1102 "goodbye" 1103 ], 1104 "Pointer": { 1105 "Bool": false, 1106 "String": "", 1107 "Bytes": "", 1108 "Int": 0, 1109 "Uint": 0, 1110 "Float": 0, 1111 "Map": {}, 1112 "StructScalars": { 1113 "Bool": false, 1114 "String": "", 1115 "Bytes": "", 1116 "Int": 0, 1117 "Uint": 0, 1118 "Float": 0 1119 }, 1120 "StructMaps": { 1121 "MapBool": {}, 1122 "MapString": {}, 1123 "MapBytes": {}, 1124 "MapInt": {}, 1125 "MapUint": {}, 1126 "MapFloat": {} 1127 }, 1128 "StructSlices": { 1129 "SliceBool": [], 1130 "SliceString": [], 1131 "SliceBytes": [], 1132 "SliceInt": [], 1133 "SliceUint": [], 1134 "SliceFloat": [] 1135 }, 1136 "Slice": [], 1137 "Array": [ 1138 "" 1139 ], 1140 "Pointer": null, 1141 "Interface": null 1142 }, 1143 "Interface": null 1144 }`, 1145 }, { 1146 name: name("Structs/Stringified"), 1147 eopts: EncodeOptions{Indent: "\t"}, 1148 in: structStringifiedAll{ 1149 Bool: true, 1150 String: "hello", 1151 Bytes: []byte{1, 2, 3}, 1152 Int: -64, // should be stringified 1153 Uint: +64, // should be stringified 1154 Float: 3.14159, // should be stringified 1155 Map: map[string]string{"key": "value"}, 1156 StructScalars: structScalars{ 1157 Bool: true, 1158 String: "hello", 1159 Bytes: []byte{1, 2, 3}, 1160 Int: -64, // should be stringified 1161 Uint: +64, // should be stringified 1162 Float: 3.14159, // should be stringified 1163 }, 1164 StructMaps: structMaps{ 1165 MapBool: map[string]bool{"": true}, 1166 MapString: map[string]string{"": "hello"}, 1167 MapBytes: map[string][]byte{"": {1, 2, 3}}, 1168 MapInt: map[string]int64{"": -64}, // should be stringified 1169 MapUint: map[string]uint64{"": +64}, // should be stringified 1170 MapFloat: map[string]float64{"": 3.14159}, // should be stringified 1171 }, 1172 StructSlices: structSlices{ 1173 SliceBool: []bool{true}, 1174 SliceString: []string{"hello"}, 1175 SliceBytes: [][]byte{{1, 2, 3}}, 1176 SliceInt: []int64{-64}, // should be stringified 1177 SliceUint: []uint64{+64}, // should be stringified 1178 SliceFloat: []float64{3.14159}, // should be stringified 1179 }, 1180 Slice: []string{"fizz", "buzz"}, 1181 Array: [1]string{"goodbye"}, 1182 Pointer: new(structStringifiedAll), // should be stringified 1183 Interface: (*structStringifiedAll)(nil), 1184 }, 1185 want: `{ 1186 "Bool": true, 1187 "String": "hello", 1188 "Bytes": "AQID", 1189 "Int": "-64", 1190 "Uint": "64", 1191 "Float": "3.14159", 1192 "Map": { 1193 "key": "value" 1194 }, 1195 "StructScalars": { 1196 "Bool": true, 1197 "String": "hello", 1198 "Bytes": "AQID", 1199 "Int": "-64", 1200 "Uint": "64", 1201 "Float": "3.14159" 1202 }, 1203 "StructMaps": { 1204 "MapBool": { 1205 "": true 1206 }, 1207 "MapString": { 1208 "": "hello" 1209 }, 1210 "MapBytes": { 1211 "": "AQID" 1212 }, 1213 "MapInt": { 1214 "": "-64" 1215 }, 1216 "MapUint": { 1217 "": "64" 1218 }, 1219 "MapFloat": { 1220 "": "3.14159" 1221 } 1222 }, 1223 "StructSlices": { 1224 "SliceBool": [ 1225 true 1226 ], 1227 "SliceString": [ 1228 "hello" 1229 ], 1230 "SliceBytes": [ 1231 "AQID" 1232 ], 1233 "SliceInt": [ 1234 "-64" 1235 ], 1236 "SliceUint": [ 1237 "64" 1238 ], 1239 "SliceFloat": [ 1240 "3.14159" 1241 ] 1242 }, 1243 "Slice": [ 1244 "fizz", 1245 "buzz" 1246 ], 1247 "Array": [ 1248 "goodbye" 1249 ], 1250 "Pointer": { 1251 "Bool": false, 1252 "String": "", 1253 "Bytes": "", 1254 "Int": "0", 1255 "Uint": "0", 1256 "Float": "0", 1257 "Map": {}, 1258 "StructScalars": { 1259 "Bool": false, 1260 "String": "", 1261 "Bytes": "", 1262 "Int": "0", 1263 "Uint": "0", 1264 "Float": "0" 1265 }, 1266 "StructMaps": { 1267 "MapBool": {}, 1268 "MapString": {}, 1269 "MapBytes": {}, 1270 "MapInt": {}, 1271 "MapUint": {}, 1272 "MapFloat": {} 1273 }, 1274 "StructSlices": { 1275 "SliceBool": [], 1276 "SliceString": [], 1277 "SliceBytes": [], 1278 "SliceInt": [], 1279 "SliceUint": [], 1280 "SliceFloat": [] 1281 }, 1282 "Slice": [], 1283 "Array": [ 1284 "" 1285 ], 1286 "Pointer": null, 1287 "Interface": null 1288 }, 1289 "Interface": null 1290 }`, 1291 }, { 1292 name: name("Structs/Stringified/Escaped"), 1293 eopts: EncodeOptions{Indent: "\t", EscapeRune: func(rune) bool { return true }}, 1294 in: structStringifiedAll{ 1295 Bool: true, 1296 String: "hello", 1297 Bytes: []byte{1, 2, 3}, 1298 Int: -64, // should be stringified and escaped 1299 Uint: +64, // should be stringified and escaped 1300 Float: 3.14159, // should be stringified and escaped 1301 }, 1302 want: `{ 1303 "\u0042\u006f\u006f\u006c": true, 1304 "\u0053\u0074\u0072\u0069\u006e\u0067": "\u0068\u0065\u006c\u006c\u006f", 1305 "\u0042\u0079\u0074\u0065\u0073": "\u0041\u0051\u0049\u0044", 1306 "\u0049\u006e\u0074": "\u002d\u0036\u0034", 1307 "\u0055\u0069\u006e\u0074": "\u0036\u0034", 1308 "\u0046\u006c\u006f\u0061\u0074": "\u0033\u002e\u0031\u0034\u0031\u0035\u0039", 1309 "\u004d\u0061\u0070": {}, 1310 "\u0053\u0074\u0072\u0075\u0063\u0074\u0053\u0063\u0061\u006c\u0061\u0072\u0073": { 1311 "\u0042\u006f\u006f\u006c": false, 1312 "\u0053\u0074\u0072\u0069\u006e\u0067": "", 1313 "\u0042\u0079\u0074\u0065\u0073": "", 1314 "\u0049\u006e\u0074": "\u0030", 1315 "\u0055\u0069\u006e\u0074": "\u0030", 1316 "\u0046\u006c\u006f\u0061\u0074": "\u0030" 1317 }, 1318 "\u0053\u0074\u0072\u0075\u0063\u0074\u004d\u0061\u0070\u0073": { 1319 "\u004d\u0061\u0070\u0042\u006f\u006f\u006c": {}, 1320 "\u004d\u0061\u0070\u0053\u0074\u0072\u0069\u006e\u0067": {}, 1321 "\u004d\u0061\u0070\u0042\u0079\u0074\u0065\u0073": {}, 1322 "\u004d\u0061\u0070\u0049\u006e\u0074": {}, 1323 "\u004d\u0061\u0070\u0055\u0069\u006e\u0074": {}, 1324 "\u004d\u0061\u0070\u0046\u006c\u006f\u0061\u0074": {} 1325 }, 1326 "\u0053\u0074\u0072\u0075\u0063\u0074\u0053\u006c\u0069\u0063\u0065\u0073": { 1327 "\u0053\u006c\u0069\u0063\u0065\u0042\u006f\u006f\u006c": [], 1328 "\u0053\u006c\u0069\u0063\u0065\u0053\u0074\u0072\u0069\u006e\u0067": [], 1329 "\u0053\u006c\u0069\u0063\u0065\u0042\u0079\u0074\u0065\u0073": [], 1330 "\u0053\u006c\u0069\u0063\u0065\u0049\u006e\u0074": [], 1331 "\u0053\u006c\u0069\u0063\u0065\u0055\u0069\u006e\u0074": [], 1332 "\u0053\u006c\u0069\u0063\u0065\u0046\u006c\u006f\u0061\u0074": [] 1333 }, 1334 "\u0053\u006c\u0069\u0063\u0065": [], 1335 "\u0041\u0072\u0072\u0061\u0079": [ 1336 "" 1337 ], 1338 "\u0050\u006f\u0069\u006e\u0074\u0065\u0072": null, 1339 "\u0049\u006e\u0074\u0065\u0072\u0066\u0061\u0063\u0065": null 1340 }`, 1341 }, { 1342 name: name("Structs/OmitZero/Zero"), 1343 in: structOmitZeroAll{}, 1344 want: `{}`, 1345 }, { 1346 name: name("Structs/OmitZero/NonZero"), 1347 eopts: EncodeOptions{Indent: "\t"}, 1348 in: structOmitZeroAll{ 1349 Bool: true, // not omitted since true is non-zero 1350 String: " ", // not omitted since non-empty string is non-zero 1351 Bytes: []byte{}, // not omitted since allocated slice is non-zero 1352 Int: 1, // not omitted since 1 is non-zero 1353 Uint: 1, // not omitted since 1 is non-zero 1354 Float: math.Copysign(0, -1), // not omitted since -0 is technically non-zero 1355 Map: map[string]string{}, // not omitted since allocated map is non-zero 1356 StructScalars: structScalars{unexported: true}, // not omitted since unexported is non-zero 1357 StructSlices: structSlices{Ignored: true}, // not omitted since Ignored is non-zero 1358 StructMaps: structMaps{MapBool: map[string]bool{}}, // not omitted since MapBool is non-zero 1359 Slice: []string{}, // not omitted since allocated slice is non-zero 1360 Array: [1]string{" "}, // not omitted since single array element is non-zero 1361 Pointer: new(structOmitZeroAll), // not omitted since pointer is non-zero (even if all fields of the struct value are zero) 1362 Interface: (*structOmitZeroAll)(nil), // not omitted since interface value is non-zero (even if interface value is a nil pointer) 1363 }, 1364 want: `{ 1365 "Bool": true, 1366 "String": " ", 1367 "Bytes": "", 1368 "Int": 1, 1369 "Uint": 1, 1370 "Float": -0, 1371 "Map": {}, 1372 "StructScalars": { 1373 "Bool": false, 1374 "String": "", 1375 "Bytes": "", 1376 "Int": 0, 1377 "Uint": 0, 1378 "Float": 0 1379 }, 1380 "StructMaps": { 1381 "MapBool": {}, 1382 "MapString": {}, 1383 "MapBytes": {}, 1384 "MapInt": {}, 1385 "MapUint": {}, 1386 "MapFloat": {} 1387 }, 1388 "StructSlices": { 1389 "SliceBool": [], 1390 "SliceString": [], 1391 "SliceBytes": [], 1392 "SliceInt": [], 1393 "SliceUint": [], 1394 "SliceFloat": [] 1395 }, 1396 "Slice": [], 1397 "Array": [ 1398 " " 1399 ], 1400 "Pointer": {}, 1401 "Interface": null 1402 }`, 1403 }, { 1404 name: name("Structs/OmitZeroMethod/Zero"), 1405 in: structOmitZeroMethodAll{}, 1406 want: `{"ValueNeverZero":"","PointerNeverZero":""}`, 1407 }, { 1408 name: name("Structs/OmitZeroMethod/NonZero"), 1409 eopts: EncodeOptions{Indent: "\t"}, 1410 in: structOmitZeroMethodAll{ 1411 ValueAlwaysZero: valueAlwaysZero("nonzero"), 1412 ValueNeverZero: valueNeverZero("nonzero"), 1413 PointerAlwaysZero: pointerAlwaysZero("nonzero"), 1414 PointerNeverZero: pointerNeverZero("nonzero"), 1415 PointerValueAlwaysZero: addr(valueAlwaysZero("nonzero")), 1416 PointerValueNeverZero: addr(valueNeverZero("nonzero")), 1417 PointerPointerAlwaysZero: addr(pointerAlwaysZero("nonzero")), 1418 PointerPointerNeverZero: addr(pointerNeverZero("nonzero")), 1419 PointerPointerValueAlwaysZero: addr(addr(valueAlwaysZero("nonzero"))), // marshaled since **valueAlwaysZero does not implement IsZero 1420 PointerPointerValueNeverZero: addr(addr(valueNeverZero("nonzero"))), 1421 PointerPointerPointerAlwaysZero: addr(addr(pointerAlwaysZero("nonzero"))), // marshaled since **pointerAlwaysZero does not implement IsZero 1422 PointerPointerPointerNeverZero: addr(addr(pointerNeverZero("nonzero"))), 1423 }, 1424 want: `{ 1425 "ValueNeverZero": "nonzero", 1426 "PointerNeverZero": "nonzero", 1427 "PointerValueNeverZero": "nonzero", 1428 "PointerPointerNeverZero": "nonzero", 1429 "PointerPointerValueAlwaysZero": "nonzero", 1430 "PointerPointerValueNeverZero": "nonzero", 1431 "PointerPointerPointerAlwaysZero": "nonzero", 1432 "PointerPointerPointerNeverZero": "nonzero" 1433 }`, 1434 }, { 1435 name: name("Structs/OmitZeroMethod/Interface/Zero"), 1436 eopts: EncodeOptions{Indent: "\t"}, 1437 in: structOmitZeroMethodInterfaceAll{}, 1438 want: `{}`, 1439 }, { 1440 name: name("Structs/OmitZeroMethod/Interface/PartialZero"), 1441 eopts: EncodeOptions{Indent: "\t"}, 1442 in: structOmitZeroMethodInterfaceAll{ 1443 ValueAlwaysZero: valueAlwaysZero(""), 1444 ValueNeverZero: valueNeverZero(""), 1445 PointerValueAlwaysZero: (*valueAlwaysZero)(nil), 1446 PointerValueNeverZero: (*valueNeverZero)(nil), // nil pointer, so method not called 1447 PointerPointerAlwaysZero: (*pointerAlwaysZero)(nil), 1448 PointerPointerNeverZero: (*pointerNeverZero)(nil), // nil pointer, so method not called 1449 }, 1450 want: `{ 1451 "ValueNeverZero": "" 1452 }`, 1453 }, { 1454 name: name("Structs/OmitZeroMethod/Interface/NonZero"), 1455 eopts: EncodeOptions{Indent: "\t"}, 1456 in: structOmitZeroMethodInterfaceAll{ 1457 ValueAlwaysZero: valueAlwaysZero("nonzero"), 1458 ValueNeverZero: valueNeverZero("nonzero"), 1459 PointerValueAlwaysZero: addr(valueAlwaysZero("nonzero")), 1460 PointerValueNeverZero: addr(valueNeverZero("nonzero")), 1461 PointerPointerAlwaysZero: addr(pointerAlwaysZero("nonzero")), 1462 PointerPointerNeverZero: addr(pointerNeverZero("nonzero")), 1463 }, 1464 want: `{ 1465 "ValueNeverZero": "nonzero", 1466 "PointerValueNeverZero": "nonzero", 1467 "PointerPointerNeverZero": "nonzero" 1468 }`, 1469 }, { 1470 name: name("Structs/OmitEmpty/Zero"), 1471 eopts: EncodeOptions{Indent: "\t"}, 1472 in: structOmitEmptyAll{}, 1473 want: `{ 1474 "Bool": false, 1475 "StringNonEmpty": "value", 1476 "BytesNonEmpty": [ 1477 "value" 1478 ], 1479 "Float": 0, 1480 "MapNonEmpty": { 1481 "key": "value" 1482 }, 1483 "SliceNonEmpty": [ 1484 "value" 1485 ] 1486 }`, 1487 }, { 1488 name: name("Structs/OmitEmpty/EmptyNonZero"), 1489 eopts: EncodeOptions{Indent: "\t"}, 1490 in: structOmitEmptyAll{ 1491 String: string(""), 1492 StringEmpty: stringMarshalEmpty(""), 1493 StringNonEmpty: stringMarshalNonEmpty(""), 1494 PointerString: addr(string("")), 1495 PointerStringEmpty: addr(stringMarshalEmpty("")), 1496 PointerStringNonEmpty: addr(stringMarshalNonEmpty("")), 1497 Bytes: []byte(""), 1498 BytesEmpty: bytesMarshalEmpty([]byte("")), 1499 BytesNonEmpty: bytesMarshalNonEmpty([]byte("")), 1500 PointerBytes: addr([]byte("")), 1501 PointerBytesEmpty: addr(bytesMarshalEmpty([]byte(""))), 1502 PointerBytesNonEmpty: addr(bytesMarshalNonEmpty([]byte(""))), 1503 Map: map[string]string{}, 1504 MapEmpty: mapMarshalEmpty{}, 1505 MapNonEmpty: mapMarshalNonEmpty{}, 1506 PointerMap: addr(map[string]string{}), 1507 PointerMapEmpty: addr(mapMarshalEmpty{}), 1508 PointerMapNonEmpty: addr(mapMarshalNonEmpty{}), 1509 Slice: []string{}, 1510 SliceEmpty: sliceMarshalEmpty{}, 1511 SliceNonEmpty: sliceMarshalNonEmpty{}, 1512 PointerSlice: addr([]string{}), 1513 PointerSliceEmpty: addr(sliceMarshalEmpty{}), 1514 PointerSliceNonEmpty: addr(sliceMarshalNonEmpty{}), 1515 Pointer: &structOmitZeroEmptyAll{}, 1516 Interface: []string{}, 1517 }, 1518 want: `{ 1519 "Bool": false, 1520 "StringNonEmpty": "value", 1521 "PointerStringNonEmpty": "value", 1522 "BytesNonEmpty": [ 1523 "value" 1524 ], 1525 "PointerBytesNonEmpty": [ 1526 "value" 1527 ], 1528 "Float": 0, 1529 "MapNonEmpty": { 1530 "key": "value" 1531 }, 1532 "PointerMapNonEmpty": { 1533 "key": "value" 1534 }, 1535 "SliceNonEmpty": [ 1536 "value" 1537 ], 1538 "PointerSliceNonEmpty": [ 1539 "value" 1540 ] 1541 }`, 1542 }, { 1543 name: name("Structs/OmitEmpty/NonEmpty"), 1544 eopts: EncodeOptions{Indent: "\t"}, 1545 in: structOmitEmptyAll{ 1546 Bool: true, 1547 PointerBool: addr(true), 1548 String: string("value"), 1549 StringEmpty: stringMarshalEmpty("value"), 1550 StringNonEmpty: stringMarshalNonEmpty("value"), 1551 PointerString: addr(string("value")), 1552 PointerStringEmpty: addr(stringMarshalEmpty("value")), 1553 PointerStringNonEmpty: addr(stringMarshalNonEmpty("value")), 1554 Bytes: []byte("value"), 1555 BytesEmpty: bytesMarshalEmpty([]byte("value")), 1556 BytesNonEmpty: bytesMarshalNonEmpty([]byte("value")), 1557 PointerBytes: addr([]byte("value")), 1558 PointerBytesEmpty: addr(bytesMarshalEmpty([]byte("value"))), 1559 PointerBytesNonEmpty: addr(bytesMarshalNonEmpty([]byte("value"))), 1560 Float: math.Copysign(0, -1), 1561 PointerFloat: addr(math.Copysign(0, -1)), 1562 Map: map[string]string{"": ""}, 1563 MapEmpty: mapMarshalEmpty{"key": "value"}, 1564 MapNonEmpty: mapMarshalNonEmpty{"key": "value"}, 1565 PointerMap: addr(map[string]string{"": ""}), 1566 PointerMapEmpty: addr(mapMarshalEmpty{"key": "value"}), 1567 PointerMapNonEmpty: addr(mapMarshalNonEmpty{"key": "value"}), 1568 Slice: []string{""}, 1569 SliceEmpty: sliceMarshalEmpty{"value"}, 1570 SliceNonEmpty: sliceMarshalNonEmpty{"value"}, 1571 PointerSlice: addr([]string{""}), 1572 PointerSliceEmpty: addr(sliceMarshalEmpty{"value"}), 1573 PointerSliceNonEmpty: addr(sliceMarshalNonEmpty{"value"}), 1574 Pointer: &structOmitZeroEmptyAll{Float: math.Copysign(0, -1)}, 1575 Interface: []string{""}, 1576 }, 1577 want: `{ 1578 "Bool": true, 1579 "PointerBool": true, 1580 "String": "value", 1581 "StringNonEmpty": "value", 1582 "PointerString": "value", 1583 "PointerStringNonEmpty": "value", 1584 "Bytes": "dmFsdWU=", 1585 "BytesNonEmpty": [ 1586 "value" 1587 ], 1588 "PointerBytes": "dmFsdWU=", 1589 "PointerBytesNonEmpty": [ 1590 "value" 1591 ], 1592 "Float": -0, 1593 "PointerFloat": -0, 1594 "Map": { 1595 "": "" 1596 }, 1597 "MapNonEmpty": { 1598 "key": "value" 1599 }, 1600 "PointerMap": { 1601 "": "" 1602 }, 1603 "PointerMapNonEmpty": { 1604 "key": "value" 1605 }, 1606 "Slice": [ 1607 "" 1608 ], 1609 "SliceNonEmpty": [ 1610 "value" 1611 ], 1612 "PointerSlice": [ 1613 "" 1614 ], 1615 "PointerSliceNonEmpty": [ 1616 "value" 1617 ], 1618 "Pointer": { 1619 "Float": -0 1620 }, 1621 "Interface": [ 1622 "" 1623 ] 1624 }`, 1625 }, { 1626 name: name("Structs/OmitEmpty/NonEmptyString"), 1627 in: struct { 1628 X string `json:",omitempty"` 1629 }{`"`}, 1630 want: `{"X":"\""}`, 1631 }, { 1632 name: name("Structs/OmitZeroEmpty/Zero"), 1633 in: structOmitZeroEmptyAll{}, 1634 want: `{}`, 1635 }, { 1636 name: name("Structs/OmitZeroEmpty/Empty"), 1637 in: structOmitZeroEmptyAll{ 1638 Bytes: []byte{}, 1639 Map: map[string]string{}, 1640 Slice: []string{}, 1641 Pointer: &structOmitZeroEmptyAll{}, 1642 Interface: []string{}, 1643 }, 1644 want: `{}`, 1645 }, { 1646 name: name("Structs/OmitEmpty/PathologicalDepth"), 1647 in: func() any { 1648 type X struct { 1649 X *X `json:",omitempty"` 1650 } 1651 var make func(int) *X 1652 make = func(n int) *X { 1653 if n == 0 { 1654 return nil 1655 } 1656 return &X{make(n - 1)} 1657 } 1658 return make(100) 1659 }(), 1660 want: `{}`, 1661 useWriter: true, 1662 }, { 1663 name: name("Structs/OmitEmpty/PathologicalBreadth"), 1664 in: func() any { 1665 var fields []reflect.StructField 1666 for i := 0; i < 100; i++ { 1667 fields = append(fields, reflect.StructField{ 1668 Name: fmt.Sprintf("X%d", i), 1669 Type: reflect.TypeOf(stringMarshalEmpty("")), 1670 Tag: `json:",omitempty"`, 1671 }) 1672 } 1673 return reflect.New(reflect.StructOf(fields)).Interface() 1674 }(), 1675 want: `{}`, 1676 useWriter: true, 1677 }, { 1678 name: name("Structs/OmitEmpty/PathologicalTree"), 1679 in: func() any { 1680 type X struct { 1681 XL, XR *X `json:",omitempty"` 1682 } 1683 var make func(int) *X 1684 make = func(n int) *X { 1685 if n == 0 { 1686 return nil 1687 } 1688 return &X{make(n - 1), make(n - 1)} 1689 } 1690 return make(8) 1691 }(), 1692 want: `{}`, 1693 useWriter: true, 1694 }, { 1695 name: name("Structs/OmitZeroEmpty/NonEmpty"), 1696 in: structOmitZeroEmptyAll{ 1697 Bytes: []byte("value"), 1698 Map: map[string]string{"": ""}, 1699 Slice: []string{""}, 1700 Pointer: &structOmitZeroEmptyAll{Bool: true}, 1701 Interface: []string{""}, 1702 }, 1703 want: `{"Bytes":"dmFsdWU=","Map":{"":""},"Slice":[""],"Pointer":{"Bool":true},"Interface":[""]}`, 1704 }, { 1705 name: name("Structs/Format/Bytes"), 1706 eopts: EncodeOptions{Indent: "\t"}, 1707 in: structFormatBytes{ 1708 Base16: []byte("\x01\x23\x45\x67\x89\xab\xcd\xef"), 1709 Base32: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"), 1710 Base32Hex: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"), 1711 Base64: []byte("\x00\x10\x83\x10Q\x87 \x92\x8b0ӏA\x14\x93QU\x97a\x96\x9bqן\x82\x18\xa3\x92Y\xa7\xa2\x9a\xab\xb2ۯ\xc3\x1c\xb3\xd3]\xb7㞻\xf3߿"), 1712 Base64URL: []byte("\x00\x10\x83\x10Q\x87 \x92\x8b0ӏA\x14\x93QU\x97a\x96\x9bqן\x82\x18\xa3\x92Y\xa7\xa2\x9a\xab\xb2ۯ\xc3\x1c\xb3\xd3]\xb7㞻\xf3߿"), 1713 Array: []byte{1, 2, 3, 4}, 1714 }, 1715 want: `{ 1716 "Base16": "0123456789abcdef", 1717 "Base32": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", 1718 "Base32Hex": "0123456789ABCDEFGHIJKLMNOPQRSTUV", 1719 "Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", 1720 "Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", 1721 "Array": [ 1722 1, 1723 2, 1724 3, 1725 4 1726 ] 1727 }`}, { 1728 name: name("Structs/Format/Bytes/Array"), 1729 mopts: MarshalOptions{Marshalers: MarshalFuncV1(func(in byte) ([]byte, error) { 1730 if in > 3 { 1731 return []byte("true"), nil 1732 } else { 1733 return []byte("false"), nil 1734 } 1735 })}, 1736 in: struct { 1737 Array []byte `json:",format:array"` 1738 }{ 1739 Array: []byte{1, 6, 2, 5, 3, 4}, 1740 }, 1741 want: `{"Array":[false,true,false,true,false,true]}`, 1742 }, { 1743 name: name("Structs/Format/Floats"), 1744 eopts: EncodeOptions{Indent: "\t"}, 1745 in: []structFormatFloats{ 1746 {NonFinite: math.Pi, PointerNonFinite: addr(math.Pi)}, 1747 {NonFinite: math.NaN(), PointerNonFinite: addr(math.NaN())}, 1748 {NonFinite: math.Inf(-1), PointerNonFinite: addr(math.Inf(-1))}, 1749 {NonFinite: math.Inf(+1), PointerNonFinite: addr(math.Inf(+1))}, 1750 }, 1751 want: `[ 1752 { 1753 "NonFinite": 3.141592653589793, 1754 "PointerNonFinite": 3.141592653589793 1755 }, 1756 { 1757 "NonFinite": "NaN", 1758 "PointerNonFinite": "NaN" 1759 }, 1760 { 1761 "NonFinite": "-Infinity", 1762 "PointerNonFinite": "-Infinity" 1763 }, 1764 { 1765 "NonFinite": "Infinity", 1766 "PointerNonFinite": "Infinity" 1767 } 1768 ]`, 1769 }, { 1770 name: name("Structs/Format/Maps"), 1771 eopts: EncodeOptions{Indent: "\t"}, 1772 in: []structFormatMaps{ 1773 {EmitNull: nil, PointerEmitNull: new(map[string]string)}, 1774 {EmitNull: map[string]string{}, PointerEmitNull: addr(map[string]string{})}, 1775 {EmitNull: map[string]string{"k": "v"}, PointerEmitNull: addr(map[string]string{"k": "v"})}, 1776 }, 1777 want: `[ 1778 { 1779 "EmitNull": null, 1780 "PointerEmitNull": null 1781 }, 1782 { 1783 "EmitNull": {}, 1784 "PointerEmitNull": {} 1785 }, 1786 { 1787 "EmitNull": { 1788 "k": "v" 1789 }, 1790 "PointerEmitNull": { 1791 "k": "v" 1792 } 1793 } 1794 ]`, 1795 }, { 1796 name: name("Structs/Format/Slices"), 1797 eopts: EncodeOptions{Indent: "\t"}, 1798 in: []structFormatSlices{ 1799 {EmitNull: nil, PointerEmitNull: new([]string)}, 1800 {EmitNull: []string{}, PointerEmitNull: addr([]string{})}, 1801 {EmitNull: []string{"v"}, PointerEmitNull: addr([]string{"v"})}, 1802 }, 1803 want: `[ 1804 { 1805 "EmitNull": null, 1806 "PointerEmitNull": null 1807 }, 1808 { 1809 "EmitNull": [], 1810 "PointerEmitNull": [] 1811 }, 1812 { 1813 "EmitNull": [ 1814 "v" 1815 ], 1816 "PointerEmitNull": [ 1817 "v" 1818 ] 1819 } 1820 ]`, 1821 }, { 1822 name: name("Structs/Format/Invalid/Bool"), 1823 in: structFormatInvalid{Bool: true}, 1824 want: `{"Bool"`, 1825 wantErr: &SemanticError{action: "marshal", GoType: boolType, Err: errors.New(`invalid format flag: "invalid"`)}, 1826 }, { 1827 name: name("Structs/Format/Invalid/String"), 1828 in: structFormatInvalid{String: "string"}, 1829 want: `{"String"`, 1830 wantErr: &SemanticError{action: "marshal", GoType: stringType, Err: errors.New(`invalid format flag: "invalid"`)}, 1831 }, { 1832 name: name("Structs/Format/Invalid/Bytes"), 1833 in: structFormatInvalid{Bytes: []byte("bytes")}, 1834 want: `{"Bytes"`, 1835 wantErr: &SemanticError{action: "marshal", GoType: bytesType, Err: errors.New(`invalid format flag: "invalid"`)}, 1836 }, { 1837 name: name("Structs/Format/Invalid/Int"), 1838 in: structFormatInvalid{Int: 1}, 1839 want: `{"Int"`, 1840 wantErr: &SemanticError{action: "marshal", GoType: int64Type, Err: errors.New(`invalid format flag: "invalid"`)}, 1841 }, { 1842 name: name("Structs/Format/Invalid/Uint"), 1843 in: structFormatInvalid{Uint: 1}, 1844 want: `{"Uint"`, 1845 wantErr: &SemanticError{action: "marshal", GoType: uint64Type, Err: errors.New(`invalid format flag: "invalid"`)}, 1846 }, { 1847 name: name("Structs/Format/Invalid/Float"), 1848 in: structFormatInvalid{Float: 1}, 1849 want: `{"Float"`, 1850 wantErr: &SemanticError{action: "marshal", GoType: float64Type, Err: errors.New(`invalid format flag: "invalid"`)}, 1851 }, { 1852 name: name("Structs/Format/Invalid/Map"), 1853 in: structFormatInvalid{Map: map[string]string{}}, 1854 want: `{"Map"`, 1855 wantErr: &SemanticError{action: "marshal", GoType: mapStringStringType, Err: errors.New(`invalid format flag: "invalid"`)}, 1856 }, { 1857 name: name("Structs/Format/Invalid/Struct"), 1858 in: structFormatInvalid{Struct: structAll{Bool: true}}, 1859 want: `{"Struct"`, 1860 wantErr: &SemanticError{action: "marshal", GoType: structAllType, Err: errors.New(`invalid format flag: "invalid"`)}, 1861 }, { 1862 name: name("Structs/Format/Invalid/Slice"), 1863 in: structFormatInvalid{Slice: []string{}}, 1864 want: `{"Slice"`, 1865 wantErr: &SemanticError{action: "marshal", GoType: sliceStringType, Err: errors.New(`invalid format flag: "invalid"`)}, 1866 }, { 1867 name: name("Structs/Format/Invalid/Array"), 1868 in: structFormatInvalid{Array: [1]string{"string"}}, 1869 want: `{"Array"`, 1870 wantErr: &SemanticError{action: "marshal", GoType: array1StringType, Err: errors.New(`invalid format flag: "invalid"`)}, 1871 }, { 1872 name: name("Structs/Format/Invalid/Interface"), 1873 in: structFormatInvalid{Interface: "anything"}, 1874 want: `{"Interface"`, 1875 wantErr: &SemanticError{action: "marshal", GoType: anyType, Err: errors.New(`invalid format flag: "invalid"`)}, 1876 }, { 1877 name: name("Structs/Inline/Zero"), 1878 in: structInlined{}, 1879 want: `{"D":""}`, 1880 }, { 1881 name: name("Structs/Inline/Alloc"), 1882 in: structInlined{ 1883 X: structInlinedL1{ 1884 X: &structInlinedL2{}, 1885 StructEmbed1: StructEmbed1{}, 1886 }, 1887 StructEmbed2: &StructEmbed2{}, 1888 }, 1889 want: `{"A":"","B":"","D":"","E":"","F":"","G":""}`, 1890 }, { 1891 name: name("Structs/Inline/NonZero"), 1892 in: structInlined{ 1893 X: structInlinedL1{ 1894 X: &structInlinedL2{A: "A1", B: "B1", C: "C1"}, 1895 StructEmbed1: StructEmbed1{C: "C2", D: "D2", E: "E2"}, 1896 }, 1897 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"}, 1898 }, 1899 want: `{"A":"A1","B":"B1","D":"D2","E":"E3","F":"F3","G":"G3"}`, 1900 }, { 1901 name: name("Structs/Inline/DualCycle"), 1902 in: cyclicA{ 1903 B1: cyclicB{F: 1}, // B1.F ignored since it conflicts with B2.F 1904 B2: cyclicB{F: 2}, // B2.F ignored since it conflicts with B1.F 1905 }, 1906 want: `{}`, 1907 }, { 1908 name: name("Structs/InlinedFallback/RawValue/Nil"), 1909 in: structInlineRawValue{X: RawValue(nil)}, 1910 want: `{}`, 1911 }, { 1912 name: name("Structs/InlinedFallback/RawValue/Empty"), 1913 in: structInlineRawValue{X: RawValue("")}, 1914 want: `{}`, 1915 }, { 1916 name: name("Structs/InlinedFallback/RawValue/NonEmptyN1"), 1917 in: structInlineRawValue{X: RawValue(` { "fizz" : "buzz" } `)}, 1918 want: `{"fizz":"buzz"}`, 1919 }, { 1920 name: name("Structs/InlinedFallback/RawValue/NonEmptyN2"), 1921 in: structInlineRawValue{X: RawValue(` { "fizz" : "buzz" , "foo" : "bar" } `)}, 1922 want: `{"fizz":"buzz","foo":"bar"}`, 1923 }, { 1924 name: name("Structs/InlinedFallback/RawValue/NonEmptyWithOthers"), 1925 in: structInlineRawValue{ 1926 A: 1, 1927 X: RawValue(` { "fizz" : "buzz" , "foo" : "bar" } `), 1928 B: 2, 1929 }, 1930 // NOTE: Inlined fallback fields are always serialized last. 1931 want: `{"A":1,"B":2,"fizz":"buzz","foo":"bar"}`, 1932 }, { 1933 name: name("Structs/InlinedFallback/RawValue/RejectDuplicateNames"), 1934 eopts: EncodeOptions{AllowDuplicateNames: false}, 1935 in: structInlineRawValue{X: RawValue(` { "fizz" : "buzz" , "fizz" : "buzz" } `)}, 1936 want: `{"fizz":"buzz"`, 1937 wantErr: &SyntacticError{str: `duplicate name "fizz" in object`}, 1938 }, { 1939 name: name("Structs/InlinedFallback/RawValue/AllowDuplicateNames"), 1940 eopts: EncodeOptions{AllowDuplicateNames: true}, 1941 in: structInlineRawValue{X: RawValue(` { "fizz" : "buzz" , "fizz" : "buzz" } `)}, 1942 want: `{"fizz":"buzz","fizz":"buzz"}`, 1943 }, { 1944 name: name("Structs/InlinedFallback/RawValue/RejectInvalidUTF8"), 1945 eopts: EncodeOptions{AllowInvalidUTF8: false}, 1946 in: structInlineRawValue{X: RawValue(`{"` + "\xde\xad\xbe\xef" + `":"value"}`)}, 1947 want: `{`, 1948 wantErr: &SyntacticError{str: "invalid UTF-8 within string"}, 1949 }, { 1950 name: name("Structs/InlinedFallback/RawValue/AllowInvalidUTF8"), 1951 eopts: EncodeOptions{AllowInvalidUTF8: true}, 1952 in: structInlineRawValue{X: RawValue(`{"` + "\xde\xad\xbe\xef" + `":"value"}`)}, 1953 want: `{"ޭ��":"value"}`, 1954 }, { 1955 name: name("Structs/InlinedFallback/RawValue/InvalidWhitespace"), 1956 in: structInlineRawValue{X: RawValue("\n\r\t ")}, 1957 want: `{`, 1958 wantErr: &SemanticError{action: "marshal", GoType: rawValueType, Err: io.EOF}, 1959 }, { 1960 name: name("Structs/InlinedFallback/RawValue/InvalidObject"), 1961 in: structInlineRawValue{X: RawValue(` true `)}, 1962 want: `{`, 1963 wantErr: &SemanticError{action: "marshal", JSONKind: 't', GoType: rawValueType, Err: errors.New("inlined raw value must be a JSON object")}, 1964 }, { 1965 name: name("Structs/InlinedFallback/RawValue/InvalidObjectName"), 1966 in: structInlineRawValue{X: RawValue(` { true : false } `)}, 1967 want: `{`, 1968 wantErr: &SemanticError{action: "marshal", GoType: rawValueType, Err: errMissingName.withOffset(int64(len(" { ")))}, 1969 }, { 1970 name: name("Structs/InlinedFallback/RawValue/InvalidObjectEnd"), 1971 in: structInlineRawValue{X: RawValue(` { "name" : false , } `)}, 1972 want: `{"name":false`, 1973 wantErr: &SemanticError{action: "marshal", GoType: rawValueType, Err: newInvalidCharacterError([]byte(","), "before next token").withOffset(int64(len(` { "name" : false `)))}, 1974 }, { 1975 name: name("Structs/InlinedFallback/RawValue/InvalidDualObject"), 1976 in: structInlineRawValue{X: RawValue(`{}{}`)}, 1977 want: `{`, 1978 wantErr: &SemanticError{action: "marshal", GoType: rawValueType, Err: newInvalidCharacterError([]byte("{"), "after top-level value")}, 1979 }, { 1980 name: name("Structs/InlinedFallback/RawValue/Nested/Nil"), 1981 in: structInlinePointerInlineRawValue{}, 1982 want: `{}`, 1983 }, { 1984 name: name("Structs/InlinedFallback/PointerRawValue/Nil"), 1985 in: structInlinePointerRawValue{}, 1986 want: `{}`, 1987 }, { 1988 name: name("Structs/InlinedFallback/PointerRawValue/NonEmpty"), 1989 in: structInlinePointerRawValue{X: addr(RawValue(` { "fizz" : "buzz" } `))}, 1990 want: `{"fizz":"buzz"}`, 1991 }, { 1992 name: name("Structs/InlinedFallback/PointerRawValue/Nested/Nil"), 1993 in: structInlineInlinePointerRawValue{}, 1994 want: `{}`, 1995 }, { 1996 name: name("Structs/InlinedFallback/MapStringAny/Nil"), 1997 in: structInlineMapStringAny{X: nil}, 1998 want: `{}`, 1999 }, { 2000 name: name("Structs/InlinedFallback/MapStringAny/Empty"), 2001 in: structInlineMapStringAny{X: make(jsonObject)}, 2002 want: `{}`, 2003 }, { 2004 name: name("Structs/InlinedFallback/MapStringAny/NonEmptyN1"), 2005 in: structInlineMapStringAny{X: jsonObject{"fizz": nil}}, 2006 want: `{"fizz":null}`, 2007 }, { 2008 name: name("Structs/InlinedFallback/MapStringAny/NonEmptyN2"), 2009 in: structInlineMapStringAny{X: jsonObject{"fizz": time.Time{}, "buzz": math.Pi}}, 2010 want: `{"buzz":3.141592653589793,"fizz":"0001-01-01T00:00:00Z"}`, 2011 canonicalize: true, 2012 }, { 2013 name: name("Structs/InlinedFallback/MapStringAny/NonEmptyWithOthers"), 2014 in: structInlineMapStringAny{ 2015 A: 1, 2016 X: jsonObject{"fizz": nil}, 2017 B: 2, 2018 }, 2019 // NOTE: Inlined fallback fields are always serialized last. 2020 want: `{"A":1,"B":2,"fizz":null}`, 2021 }, { 2022 name: name("Structs/InlinedFallback/MapStringAny/RejectInvalidUTF8"), 2023 eopts: EncodeOptions{AllowInvalidUTF8: false}, 2024 in: structInlineMapStringAny{X: jsonObject{"\xde\xad\xbe\xef": nil}}, 2025 want: `{`, 2026 wantErr: &SyntacticError{str: "invalid UTF-8 within string"}, 2027 }, { 2028 name: name("Structs/InlinedFallback/MapStringAny/AllowInvalidUTF8"), 2029 eopts: EncodeOptions{AllowInvalidUTF8: true}, 2030 in: structInlineMapStringAny{X: jsonObject{"\xde\xad\xbe\xef": nil}}, 2031 want: `{"ޭ��":null}`, 2032 }, { 2033 name: name("Structs/InlinedFallback/MapStringAny/InvalidValue"), 2034 eopts: EncodeOptions{AllowInvalidUTF8: true}, 2035 in: structInlineMapStringAny{X: jsonObject{"name": make(chan string)}}, 2036 want: `{"name"`, 2037 wantErr: &SemanticError{action: "marshal", GoType: chanStringType}, 2038 }, { 2039 name: name("Structs/InlinedFallback/MapStringAny/Nested/Nil"), 2040 in: structInlinePointerInlineMapStringAny{}, 2041 want: `{}`, 2042 }, { 2043 name: name("Structs/InlinedFallback/MapStringAny/MarshalFuncV1"), 2044 mopts: MarshalOptions{ 2045 Marshalers: MarshalFuncV1(func(v float64) ([]byte, error) { 2046 return []byte(fmt.Sprintf(`"%v"`, v)), nil 2047 }), 2048 }, 2049 in: structInlineMapStringAny{X: jsonObject{"fizz": 3.14159}}, 2050 want: `{"fizz":"3.14159"}`, 2051 }, { 2052 name: name("Structs/InlinedFallback/PointerMapStringAny/Nil"), 2053 in: structInlinePointerMapStringAny{X: nil}, 2054 want: `{}`, 2055 }, { 2056 name: name("Structs/InlinedFallback/PointerMapStringAny/NonEmpty"), 2057 in: structInlinePointerMapStringAny{X: addr(jsonObject{"name": "value"})}, 2058 want: `{"name":"value"}`, 2059 }, { 2060 name: name("Structs/InlinedFallback/PointerMapStringAny/Nested/Nil"), 2061 in: structInlineInlinePointerMapStringAny{}, 2062 want: `{}`, 2063 }, { 2064 name: name("Structs/InlinedFallback/MapStringInt"), 2065 in: structInlineMapStringInt{ 2066 X: map[string]int{"zero": 0, "one": 1, "two": 2}, 2067 }, 2068 want: `{"one":1,"two":2,"zero":0}`, 2069 canonicalize: true, 2070 }, { 2071 name: name("Structs/InlinedFallback/MapStringInt/Deterministic"), 2072 mopts: MarshalOptions{Deterministic: true}, 2073 in: structInlineMapStringInt{ 2074 X: map[string]int{"zero": 0, "one": 1, "two": 2}, 2075 }, 2076 want: `{"one":1,"two":2,"zero":0}`, 2077 }, { 2078 name: name("Structs/InlinedFallback/MapStringInt/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"), 2079 mopts: MarshalOptions{Deterministic: true}, 2080 eopts: EncodeOptions{AllowInvalidUTF8: true, AllowDuplicateNames: false}, 2081 in: structInlineMapStringInt{ 2082 X: map[string]int{"\xff": 0, "\xfe": 1}, 2083 }, 2084 want: `{"�":1`, 2085 wantErr: &SyntacticError{str: `duplicate name "�" in object`}, 2086 }, { 2087 name: name("Structs/InlinedFallback/MapStringInt/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"), 2088 mopts: MarshalOptions{Deterministic: true}, 2089 eopts: EncodeOptions{AllowInvalidUTF8: true, AllowDuplicateNames: true}, 2090 in: structInlineMapStringInt{ 2091 X: map[string]int{"\xff": 0, "\xfe": 1}, 2092 }, 2093 want: `{"�":1,"�":0}`, 2094 }, { 2095 name: name("Structs/InlinedFallback/MapStringInt/StringifiedNumbers"), 2096 mopts: MarshalOptions{StringifyNumbers: true}, 2097 in: structInlineMapStringInt{ 2098 X: map[string]int{"zero": 0, "one": 1, "two": 2}, 2099 }, 2100 want: `{"one":"1","two":"2","zero":"0"}`, 2101 canonicalize: true, 2102 }, { 2103 name: name("Structs/InlinedFallback/MapStringInt/MarshalFuncV1"), 2104 mopts: MarshalOptions{ 2105 Marshalers: NewMarshalers( 2106 // Marshalers do not affect the string key of inlined maps. 2107 MarshalFuncV1(func(v string) ([]byte, error) { 2108 return []byte(fmt.Sprintf(`"%q"`, strings.ToUpper(v))), nil 2109 }), 2110 MarshalFuncV1(func(v int) ([]byte, error) { 2111 return []byte(fmt.Sprintf(`"%v"`, v)), nil 2112 }), 2113 ), 2114 }, 2115 in: structInlineMapStringInt{ 2116 X: map[string]int{"zero": 0, "one": 1, "two": 2}, 2117 }, 2118 want: `{"one":"1","two":"2","zero":"0"}`, 2119 canonicalize: true, 2120 }, { 2121 name: name("Structs/InlinedFallback/DiscardUnknownMembers"), 2122 mopts: MarshalOptions{DiscardUnknownMembers: true}, 2123 in: structInlineRawValue{ 2124 A: 1, 2125 X: RawValue(` { "fizz" : "buzz" } `), 2126 B: 2, 2127 }, 2128 // NOTE: DiscardUnknownMembers has no effect since this is "inline". 2129 want: `{"A":1,"B":2,"fizz":"buzz"}`, 2130 }, { 2131 name: name("Structs/UnknownFallback/DiscardUnknownMembers"), 2132 mopts: MarshalOptions{DiscardUnknownMembers: true}, 2133 in: structUnknownRawValue{ 2134 A: 1, 2135 X: RawValue(` { "fizz" : "buzz" } `), 2136 B: 2, 2137 }, 2138 want: `{"A":1,"B":2}`, 2139 }, { 2140 name: name("Structs/UnknownFallback"), 2141 in: structUnknownRawValue{ 2142 A: 1, 2143 X: RawValue(` { "fizz" : "buzz" } `), 2144 B: 2, 2145 }, 2146 want: `{"A":1,"B":2,"fizz":"buzz"}`, 2147 }, { 2148 name: name("Structs/DuplicateName/NoCaseInlineRawValue/Other"), 2149 in: structNoCaseInlineRawValue{ 2150 X: RawValue(`{"dupe":"","dupe":""}`), 2151 }, 2152 want: `{"dupe":""`, 2153 wantErr: &SyntacticError{str: `duplicate name "dupe" in object`}, 2154 }, { 2155 name: name("Structs/DuplicateName/NoCaseInlineRawValue/Other/AllowDuplicateNames"), 2156 eopts: EncodeOptions{AllowDuplicateNames: true}, 2157 in: structNoCaseInlineRawValue{ 2158 X: RawValue(`{"dupe": "", "dupe": ""}`), 2159 }, 2160 want: `{"dupe":"","dupe":""}`, 2161 }, { 2162 name: name("Structs/DuplicateName/NoCaseInlineRawValue/ExactDifferent"), 2163 in: structNoCaseInlineRawValue{ 2164 X: RawValue(`{"Aaa": "", "AaA": "", "AAa": "", "AAA": ""}`), 2165 }, 2166 want: `{"Aaa":"","AaA":"","AAa":"","AAA":""}`, 2167 }, { 2168 name: name("Structs/DuplicateName/NoCaseInlineRawValue/ExactConflict"), 2169 in: structNoCaseInlineRawValue{ 2170 X: RawValue(`{"Aaa": "", "Aaa": ""}`), 2171 }, 2172 want: `{"Aaa":""`, 2173 wantErr: &SyntacticError{str: `duplicate name "Aaa" in object`}, 2174 }, { 2175 name: name("Structs/DuplicateName/NoCaseInlineRawValue/ExactConflict/AllowDuplicateNames"), 2176 eopts: EncodeOptions{AllowDuplicateNames: true}, 2177 in: structNoCaseInlineRawValue{ 2178 X: RawValue(`{"Aaa": "", "Aaa": ""}`), 2179 }, 2180 want: `{"Aaa":"","Aaa":""}`, 2181 }, { 2182 name: name("Structs/DuplicateName/NoCaseInlineRawValue/NoCaseConflict"), 2183 in: structNoCaseInlineRawValue{ 2184 X: RawValue(`{"Aaa": "", "AaA": "", "aaa": ""}`), 2185 }, 2186 want: `{"Aaa":"","AaA":""`, 2187 wantErr: &SyntacticError{str: `duplicate name "aaa" in object`}, 2188 }, { 2189 name: name("Structs/DuplicateName/NoCaseInlineRawValue/NoCaseConflict/AllowDuplicateNames"), 2190 eopts: EncodeOptions{AllowDuplicateNames: true}, 2191 in: structNoCaseInlineRawValue{ 2192 X: RawValue(`{"Aaa": "", "AaA": "", "aaa": ""}`), 2193 }, 2194 want: `{"Aaa":"","AaA":"","aaa":""}`, 2195 }, { 2196 name: name("Structs/DuplicateName/NoCaseInlineRawValue/ExactDifferentWithField"), 2197 in: structNoCaseInlineRawValue{ 2198 AAA: "x", 2199 AaA: "x", 2200 X: RawValue(`{"Aaa": ""}`), 2201 }, 2202 want: `{"AAA":"x","AaA":"x","Aaa":""}`, 2203 }, { 2204 name: name("Structs/DuplicateName/NoCaseInlineRawValue/ExactConflictWithField"), 2205 in: structNoCaseInlineRawValue{ 2206 AAA: "x", 2207 AaA: "x", 2208 X: RawValue(`{"AAA": ""}`), 2209 }, 2210 want: `{"AAA":"x","AaA":"x"`, 2211 wantErr: &SyntacticError{str: `duplicate name "AAA" in object`}, 2212 }, { 2213 name: name("Structs/DuplicateName/NoCaseInlineRawValue/NoCaseConflictWithField"), 2214 in: structNoCaseInlineRawValue{ 2215 AAA: "x", 2216 AaA: "x", 2217 X: RawValue(`{"aaa": ""}`), 2218 }, 2219 want: `{"AAA":"x","AaA":"x"`, 2220 wantErr: &SyntacticError{str: `duplicate name "aaa" in object`}, 2221 }, { 2222 name: name("Structs/DuplicateName/NoCaseInlineMapStringAny/ExactDifferent"), 2223 in: structNoCaseInlineMapStringAny{ 2224 X: jsonObject{"Aaa": "", "AaA": "", "AAa": "", "AAA": ""}, 2225 }, 2226 want: `{"AAA":"","AAa":"","AaA":"","Aaa":""}`, 2227 canonicalize: true, 2228 }, { 2229 name: name("Structs/DuplicateName/NoCaseInlineMapStringAny/ExactDifferentWithField"), 2230 in: structNoCaseInlineMapStringAny{ 2231 AAA: "x", 2232 AaA: "x", 2233 X: jsonObject{"Aaa": ""}, 2234 }, 2235 want: `{"AAA":"x","AaA":"x","Aaa":""}`, 2236 }, { 2237 name: name("Structs/DuplicateName/NoCaseInlineMapStringAny/ExactConflictWithField"), 2238 in: structNoCaseInlineMapStringAny{ 2239 AAA: "x", 2240 AaA: "x", 2241 X: jsonObject{"AAA": ""}, 2242 }, 2243 want: `{"AAA":"x","AaA":"x"`, 2244 wantErr: &SyntacticError{str: `duplicate name "AAA" in object`}, 2245 }, { 2246 name: name("Structs/DuplicateName/NoCaseInlineMapStringAny/NoCaseConflictWithField"), 2247 in: structNoCaseInlineMapStringAny{ 2248 AAA: "x", 2249 AaA: "x", 2250 X: jsonObject{"aaa": ""}, 2251 }, 2252 want: `{"AAA":"x","AaA":"x"`, 2253 wantErr: &SyntacticError{str: `duplicate name "aaa" in object`}, 2254 }, { 2255 name: name("Structs/Invalid/Conflicting"), 2256 in: structConflicting{}, 2257 want: ``, 2258 wantErr: &SemanticError{action: "marshal", GoType: structConflictingType, Err: errors.New("Go struct fields A and B conflict over JSON object name \"conflict\"")}, 2259 }, { 2260 name: name("Structs/Invalid/NoneExported"), 2261 in: structNoneExported{}, 2262 want: ``, 2263 wantErr: &SemanticError{action: "marshal", GoType: structNoneExportedType, Err: errors.New("Go struct has no exported fields")}, 2264 }, { 2265 name: name("Structs/Invalid/MalformedTag"), 2266 in: structMalformedTag{}, 2267 want: ``, 2268 wantErr: &SemanticError{action: "marshal", GoType: structMalformedTagType, Err: errors.New("Go struct field Malformed has malformed `json` tag: invalid character '\"' at start of option (expecting Unicode letter or single quote)")}, 2269 }, { 2270 name: name("Structs/Invalid/UnexportedTag"), 2271 in: structUnexportedTag{}, 2272 want: ``, 2273 wantErr: &SemanticError{action: "marshal", GoType: structUnexportedTagType, Err: errors.New("unexported Go struct field unexported cannot have non-ignored `json:\"name\"` tag")}, 2274 }, { 2275 name: name("Structs/Invalid/UnexportedEmbedded"), 2276 in: structUnexportedEmbedded{}, 2277 want: ``, 2278 wantErr: &SemanticError{action: "marshal", GoType: structUnexportedEmbeddedType, Err: errors.New("embedded Go struct field namedString of an unexported type must be explicitly ignored with a `json:\"-\"` tag")}, 2279 }, { 2280 name: name("Structs/IgnoreInvalidFormat"), 2281 mopts: MarshalOptions{formatDepth: 1000, format: "invalid"}, 2282 in: struct{}{}, 2283 want: `{}`, 2284 }, { 2285 name: name("Slices/Interface"), 2286 in: []any{ 2287 false, true, 2288 "hello", []byte("world"), 2289 int32(-32), namedInt64(-64), 2290 uint32(+32), namedUint64(+64), 2291 float32(32.32), namedFloat64(64.64), 2292 }, 2293 want: `[false,true,"hello","d29ybGQ=",-32,-64,32,64,32.32,64.64]`, 2294 }, { 2295 name: name("Slices/Invalid/Channel"), 2296 in: [](chan string){nil}, 2297 want: `[`, 2298 wantErr: &SemanticError{action: "marshal", GoType: chanStringType}, 2299 }, { 2300 name: name("Slices/RecursiveSlice"), 2301 in: recursiveSlice{ 2302 nil, 2303 {}, 2304 {nil}, 2305 {nil, {}}, 2306 }, 2307 want: `[[],[],[[]],[[],[]]]`, 2308 }, { 2309 name: name("Slices/CyclicSlice"), 2310 in: func() recursiveSlice { 2311 s := recursiveSlice{{}} 2312 s[0] = s 2313 return s 2314 }(), 2315 want: strings.Repeat(`[`, startDetectingCyclesAfter) + `[`, 2316 wantErr: &SemanticError{action: "marshal", GoType: reflect.TypeOf(recursiveSlice{}), Err: errors.New("encountered a cycle")}, 2317 }, { 2318 name: name("Slices/IgnoreInvalidFormat"), 2319 mopts: MarshalOptions{formatDepth: 1000, format: "invalid"}, 2320 in: []string{"hello", "goodbye"}, 2321 want: `["hello","goodbye"]`, 2322 }, { 2323 name: name("Arrays/Empty"), 2324 in: [0]struct{}{}, 2325 want: `[]`, 2326 }, { 2327 name: name("Arrays/Bool"), 2328 in: [2]bool{false, true}, 2329 want: `[false,true]`, 2330 }, { 2331 name: name("Arrays/String"), 2332 in: [2]string{"hello", "goodbye"}, 2333 want: `["hello","goodbye"]`, 2334 }, { 2335 name: name("Arrays/Bytes"), 2336 in: [2][]byte{[]byte("hello"), []byte("goodbye")}, 2337 want: `["aGVsbG8=","Z29vZGJ5ZQ=="]`, 2338 }, { 2339 name: name("Arrays/Int"), 2340 in: [2]int64{math.MinInt64, math.MaxInt64}, 2341 want: `[-9223372036854775808,9223372036854775807]`, 2342 }, { 2343 name: name("Arrays/Uint"), 2344 in: [2]uint64{0, math.MaxUint64}, 2345 want: `[0,18446744073709551615]`, 2346 }, { 2347 name: name("Arrays/Float"), 2348 in: [2]float64{-math.MaxFloat64, +math.MaxFloat64}, 2349 want: `[-1.7976931348623157e+308,1.7976931348623157e+308]`, 2350 }, { 2351 name: name("Arrays/Invalid/Channel"), 2352 in: new([1]chan string), 2353 want: `[`, 2354 wantErr: &SemanticError{action: "marshal", GoType: chanStringType}, 2355 }, { 2356 name: name("Arrays/IgnoreInvalidFormat"), 2357 mopts: MarshalOptions{formatDepth: 1000, format: "invalid"}, 2358 in: [2]string{"hello", "goodbye"}, 2359 want: `["hello","goodbye"]`, 2360 }, { 2361 name: name("Pointers/NilL0"), 2362 in: (*int)(nil), 2363 want: `null`, 2364 }, { 2365 name: name("Pointers/NilL1"), 2366 in: new(*int), 2367 want: `null`, 2368 }, { 2369 name: name("Pointers/Bool"), 2370 in: addr(addr(bool(true))), 2371 want: `true`, 2372 }, { 2373 name: name("Pointers/String"), 2374 in: addr(addr(string("string"))), 2375 want: `"string"`, 2376 }, { 2377 name: name("Pointers/Bytes"), 2378 in: addr(addr([]byte("bytes"))), 2379 want: `"Ynl0ZXM="`, 2380 }, { 2381 name: name("Pointers/Int"), 2382 in: addr(addr(int(-100))), 2383 want: `-100`, 2384 }, { 2385 name: name("Pointers/Uint"), 2386 in: addr(addr(uint(100))), 2387 want: `100`, 2388 }, { 2389 name: name("Pointers/Float"), 2390 in: addr(addr(float64(3.14159))), 2391 want: `3.14159`, 2392 }, { 2393 name: name("Pointers/CyclicPointer"), 2394 in: func() *recursivePointer { 2395 p := new(recursivePointer) 2396 p.P = p 2397 return p 2398 }(), 2399 want: strings.Repeat(`{"P":`, startDetectingCyclesAfter) + `{"P"`, 2400 wantErr: &SemanticError{action: "marshal", GoType: reflect.TypeOf((*recursivePointer)(nil)), Err: errors.New("encountered a cycle")}, 2401 }, { 2402 name: name("Pointers/IgnoreInvalidFormat"), 2403 mopts: MarshalOptions{formatDepth: 1000, format: "invalid"}, 2404 in: addr(addr(bool(true))), 2405 want: `true`, 2406 }, { 2407 name: name("Interfaces/Nil/Empty"), 2408 in: [1]any{nil}, 2409 want: `[null]`, 2410 }, { 2411 name: name("Interfaces/Nil/NonEmpty"), 2412 in: [1]io.Reader{nil}, 2413 want: `[null]`, 2414 }, { 2415 name: name("Interfaces/IgnoreInvalidFormat"), 2416 mopts: MarshalOptions{formatDepth: 1000, format: "invalid"}, 2417 in: [1]io.Reader{nil}, 2418 want: `[null]`, 2419 }, { 2420 name: name("Interfaces/Any"), 2421 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}, [8]byte{}}}, 2422 want: `{"X":[null,false,"",0,{},[],"AAAAAAAAAAA="]}`, 2423 }, { 2424 name: name("Interfaces/Any/Named"), 2425 in: struct{ X namedAny }{[]namedAny{nil, false, "", 0.0, map[string]namedAny{}, []namedAny{}, [8]byte{}}}, 2426 want: `{"X":[null,false,"",0,{},[],"AAAAAAAAAAA="]}`, 2427 }, { 2428 name: name("Interfaces/Any/Stringified"), 2429 mopts: MarshalOptions{StringifyNumbers: true}, 2430 in: struct{ X any }{0.0}, 2431 want: `{"X":"0"}`, 2432 }, { 2433 name: name("Interfaces/Any/MarshalFunc/Any"), 2434 mopts: MarshalOptions{Marshalers: MarshalFuncV1(func(v any) ([]byte, error) { 2435 return []byte(`"called"`), nil 2436 })}, 2437 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}}, 2438 want: `"called"`, 2439 }, { 2440 name: name("Interfaces/Any/MarshalFunc/Bool"), 2441 mopts: MarshalOptions{Marshalers: MarshalFuncV1(func(v bool) ([]byte, error) { 2442 return []byte(`"called"`), nil 2443 })}, 2444 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}}, 2445 want: `{"X":[null,"called","",0,{},[]]}`, 2446 }, { 2447 name: name("Interfaces/Any/MarshalFunc/String"), 2448 mopts: MarshalOptions{Marshalers: MarshalFuncV1(func(v string) ([]byte, error) { 2449 return []byte(`"called"`), nil 2450 })}, 2451 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}}, 2452 want: `{"X":[null,false,"called",0,{},[]]}`, 2453 }, { 2454 name: name("Interfaces/Any/MarshalFunc/Float64"), 2455 mopts: MarshalOptions{Marshalers: MarshalFuncV1(func(v float64) ([]byte, error) { 2456 return []byte(`"called"`), nil 2457 })}, 2458 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}}, 2459 want: `{"X":[null,false,"","called",{},[]]}`, 2460 }, { 2461 name: name("Interfaces/Any/MarshalFunc/MapStringAny"), 2462 mopts: MarshalOptions{Marshalers: MarshalFuncV1(func(v map[string]any) ([]byte, error) { 2463 return []byte(`"called"`), nil 2464 })}, 2465 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}}, 2466 want: `{"X":[null,false,"",0,"called",[]]}`, 2467 }, { 2468 name: name("Interfaces/Any/MarshalFunc/SliceAny"), 2469 mopts: MarshalOptions{Marshalers: MarshalFuncV1(func(v []any) ([]byte, error) { 2470 return []byte(`"called"`), nil 2471 })}, 2472 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}}, 2473 want: `{"X":"called"}`, 2474 }, { 2475 name: name("Interfaces/Any/MarshalFunc/Bytes"), 2476 mopts: MarshalOptions{Marshalers: MarshalFuncV1(func(v [8]byte) ([]byte, error) { 2477 return []byte(`"called"`), nil 2478 })}, 2479 in: struct{ X any }{[8]byte{}}, 2480 want: `{"X":"called"}`, 2481 }, { 2482 name: name("Interfaces/Any/Maps/Empty"), 2483 in: struct{ X any }{map[string]any{}}, 2484 want: `{"X":{}}`, 2485 }, { 2486 name: name("Interfaces/Any/Maps/Empty/Multiline"), 2487 eopts: EncodeOptions{multiline: true}, 2488 in: struct{ X any }{map[string]any{}}, 2489 want: "{\n\"X\": {}\n}", 2490 }, { 2491 name: name("Interfaces/Any/Maps/NonEmpty"), 2492 in: struct{ X any }{map[string]any{"fizz": "buzz"}}, 2493 want: `{"X":{"fizz":"buzz"}}`, 2494 }, { 2495 name: name("Interfaces/Any/Maps/Deterministic"), 2496 mopts: MarshalOptions{Deterministic: true}, 2497 in: struct{ X any }{map[string]any{"alpha": "", "bravo": ""}}, 2498 want: `{"X":{"alpha":"","bravo":""}}`, 2499 }, { 2500 name: name("Interfaces/Any/Maps/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"), 2501 mopts: MarshalOptions{Deterministic: true}, 2502 eopts: EncodeOptions{AllowInvalidUTF8: true, AllowDuplicateNames: false}, 2503 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}}, 2504 want: `{"X":{"�":""`, 2505 wantErr: &SyntacticError{str: `duplicate name "�" in object`}, 2506 }, { 2507 name: name("Interfaces/Any/Maps/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"), 2508 mopts: MarshalOptions{Deterministic: true}, 2509 eopts: EncodeOptions{AllowInvalidUTF8: true, AllowDuplicateNames: true}, 2510 in: struct{ X any }{map[string]any{"\xff": "alpha", "\xfe": "bravo"}}, 2511 want: `{"X":{"�":"bravo","�":"alpha"}}`, 2512 }, { 2513 name: name("Interfaces/Any/Maps/RejectInvalidUTF8"), 2514 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}}, 2515 want: `{"X":{`, 2516 wantErr: &SyntacticError{str: "invalid UTF-8 within string"}, 2517 }, { 2518 name: name("Interfaces/Any/Maps/AllowInvalidUTF8+RejectDuplicateNames"), 2519 eopts: EncodeOptions{AllowInvalidUTF8: true}, 2520 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}}, 2521 want: `{"X":{"�":""`, 2522 wantErr: &SyntacticError{str: `duplicate name "�" in object`}, 2523 }, { 2524 name: name("Interfaces/Any/Maps/AllowInvalidUTF8+AllowDuplicateNames"), 2525 eopts: EncodeOptions{AllowInvalidUTF8: true, AllowDuplicateNames: true}, 2526 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}}, 2527 want: `{"X":{"�":"","�":""}}`, 2528 }, { 2529 name: name("Interfaces/Any/Maps/Cyclic"), 2530 in: func() any { 2531 m := map[string]any{} 2532 m[""] = m 2533 return struct{ X any }{m} 2534 }(), 2535 want: `{"X"` + strings.Repeat(`:{""`, startDetectingCyclesAfter), 2536 wantErr: &SemanticError{action: "marshal", GoType: mapStringAnyType, Err: errors.New("encountered a cycle")}, 2537 }, { 2538 name: name("Interfaces/Any/Slices/Empty"), 2539 in: struct{ X any }{[]any{}}, 2540 want: `{"X":[]}`, 2541 }, { 2542 name: name("Interfaces/Any/Slices/Empty/Multiline"), 2543 eopts: EncodeOptions{multiline: true}, 2544 in: struct{ X any }{[]any{}}, 2545 want: "{\n\"X\": []\n}", 2546 }, { 2547 name: name("Interfaces/Any/Slices/NonEmpty"), 2548 in: struct{ X any }{[]any{"fizz", "buzz"}}, 2549 want: `{"X":["fizz","buzz"]}`, 2550 }, { 2551 name: name("Interfaces/Any/Slices/Cyclic"), 2552 in: func() any { 2553 s := make([]any, 1) 2554 s[0] = s 2555 return struct{ X any }{s} 2556 }(), 2557 want: `{"X":` + strings.Repeat(`[`, startDetectingCyclesAfter), 2558 wantErr: &SemanticError{action: "marshal", GoType: sliceAnyType, Err: errors.New("encountered a cycle")}, 2559 }, { 2560 name: name("Methods/NilPointer"), 2561 in: struct{ X *allMethods }{X: (*allMethods)(nil)}, // method should not be called 2562 want: `{"X":null}`, 2563 }, { 2564 // NOTE: Fixes https://github.com/dominikh/go-tools/issues/975. 2565 name: name("Methods/NilInterface"), 2566 in: struct{ X MarshalerV2 }{X: (*allMethods)(nil)}, // method should not be called 2567 want: `{"X":null}`, 2568 }, { 2569 name: name("Methods/AllMethods"), 2570 in: struct{ X *allMethods }{X: &allMethods{method: "MarshalNextJSON", value: []byte(`"hello"`)}}, 2571 want: `{"X":"hello"}`, 2572 }, { 2573 name: name("Methods/AllMethodsExceptJSONv2"), 2574 in: struct{ X *allMethodsExceptJSONv2 }{X: &allMethodsExceptJSONv2{allMethods: allMethods{method: "MarshalJSON", value: []byte(`"hello"`)}}}, 2575 want: `{"X":"hello"}`, 2576 }, { 2577 name: name("Methods/AllMethodsExceptJSONv1"), 2578 in: struct{ X *allMethodsExceptJSONv1 }{X: &allMethodsExceptJSONv1{allMethods: allMethods{method: "MarshalNextJSON", value: []byte(`"hello"`)}}}, 2579 want: `{"X":"hello"}`, 2580 }, { 2581 name: name("Methods/AllMethodsExceptText"), 2582 in: struct{ X *allMethodsExceptText }{X: &allMethodsExceptText{allMethods: allMethods{method: "MarshalNextJSON", value: []byte(`"hello"`)}}}, 2583 want: `{"X":"hello"}`, 2584 }, { 2585 name: name("Methods/OnlyMethodJSONv2"), 2586 in: struct{ X *onlyMethodJSONv2 }{X: &onlyMethodJSONv2{allMethods: allMethods{method: "MarshalNextJSON", value: []byte(`"hello"`)}}}, 2587 want: `{"X":"hello"}`, 2588 }, { 2589 name: name("Methods/OnlyMethodJSONv1"), 2590 in: struct{ X *onlyMethodJSONv1 }{X: &onlyMethodJSONv1{allMethods: allMethods{method: "MarshalJSON", value: []byte(`"hello"`)}}}, 2591 want: `{"X":"hello"}`, 2592 }, { 2593 name: name("Methods/OnlyMethodText"), 2594 in: struct{ X *onlyMethodText }{X: &onlyMethodText{allMethods: allMethods{method: "MarshalText", value: []byte(`hello`)}}}, 2595 want: `{"X":"hello"}`, 2596 }, { 2597 name: name("Methods/IP"), 2598 in: net.IPv4(192, 168, 0, 100), 2599 want: `"192.168.0.100"`, 2600 }, { 2601 // NOTE: Fixes https://go.dev/issue/46516. 2602 name: name("Methods/Anonymous"), 2603 in: struct{ X struct{ allMethods } }{X: struct{ allMethods }{allMethods{method: "MarshalNextJSON", value: []byte(`"hello"`)}}}, 2604 want: `{"X":"hello"}`, 2605 }, { 2606 // NOTE: Fixes https://go.dev/issue/22967. 2607 name: name("Methods/Addressable"), 2608 in: struct { 2609 V allMethods 2610 M map[string]allMethods 2611 I any 2612 }{ 2613 V: allMethods{method: "MarshalNextJSON", value: []byte(`"hello"`)}, 2614 M: map[string]allMethods{"K": {method: "MarshalNextJSON", value: []byte(`"hello"`)}}, 2615 I: allMethods{method: "MarshalNextJSON", value: []byte(`"hello"`)}, 2616 }, 2617 want: `{"V":"hello","M":{"K":"hello"},"I":"hello"}`, 2618 }, { 2619 // NOTE: Fixes https://go.dev/issue/29732. 2620 name: name("Methods/MapKey/JSONv2"), 2621 in: map[structMethodJSONv2]string{{"k1"}: "v1", {"k2"}: "v2"}, 2622 want: `{"k1":"v1","k2":"v2"}`, 2623 canonicalize: true, 2624 }, { 2625 // NOTE: Fixes https://go.dev/issue/29732. 2626 name: name("Methods/MapKey/JSONv1"), 2627 in: map[structMethodJSONv1]string{{"k1"}: "v1", {"k2"}: "v2"}, 2628 want: `{"k1":"v1","k2":"v2"}`, 2629 canonicalize: true, 2630 }, { 2631 name: name("Methods/MapKey/Text"), 2632 in: map[structMethodText]string{{"k1"}: "v1", {"k2"}: "v2"}, 2633 want: `{"k1":"v1","k2":"v2"}`, 2634 canonicalize: true, 2635 }, { 2636 name: name("Methods/Invalid/JSONv2/Error"), 2637 in: marshalJSONv2Func(func(MarshalOptions, *Encoder) error { 2638 return errors.New("some error") 2639 }), 2640 wantErr: &SemanticError{action: "marshal", GoType: marshalJSONv2FuncType, Err: errors.New("some error")}, 2641 }, { 2642 name: name("Methods/Invalid/JSONv2/TooFew"), 2643 in: marshalJSONv2Func(func(MarshalOptions, *Encoder) error { 2644 return nil // do nothing 2645 }), 2646 wantErr: &SemanticError{action: "marshal", GoType: marshalJSONv2FuncType, Err: errors.New("must write exactly one JSON value")}, 2647 }, { 2648 name: name("Methods/Invalid/JSONv2/TooMany"), 2649 in: marshalJSONv2Func(func(mo MarshalOptions, enc *Encoder) error { 2650 enc.WriteToken(Null) 2651 enc.WriteToken(Null) 2652 return nil 2653 }), 2654 want: `nullnull`, 2655 wantErr: &SemanticError{action: "marshal", GoType: marshalJSONv2FuncType, Err: errors.New("must write exactly one JSON value")}, 2656 }, { 2657 name: name("Methods/Invalid/JSONv2/SkipFunc"), 2658 in: marshalJSONv2Func(func(mo MarshalOptions, enc *Encoder) error { 2659 return SkipFunc 2660 }), 2661 wantErr: &SemanticError{action: "marshal", GoType: marshalJSONv2FuncType, Err: errors.New("marshal method cannot be skipped")}, 2662 }, { 2663 name: name("Methods/Invalid/JSONv1/Error"), 2664 in: marshalJSONv1Func(func() ([]byte, error) { 2665 return nil, errors.New("some error") 2666 }), 2667 wantErr: &SemanticError{action: "marshal", GoType: marshalJSONv1FuncType, Err: errors.New("some error")}, 2668 }, { 2669 name: name("Methods/Invalid/JSONv1/Syntax"), 2670 in: marshalJSONv1Func(func() ([]byte, error) { 2671 return []byte("invalid"), nil 2672 }), 2673 wantErr: &SemanticError{action: "marshal", JSONKind: 'i', GoType: marshalJSONv1FuncType, Err: newInvalidCharacterError([]byte("i"), "at start of value")}, 2674 }, { 2675 name: name("Methods/Invalid/JSONv1/SkipFunc"), 2676 in: marshalJSONv1Func(func() ([]byte, error) { 2677 return nil, SkipFunc 2678 }), 2679 wantErr: &SemanticError{action: "marshal", GoType: marshalJSONv1FuncType, Err: errors.New("marshal method cannot be skipped")}, 2680 }, { 2681 name: name("Methods/Invalid/Text/Error"), 2682 in: marshalTextFunc(func() ([]byte, error) { 2683 return nil, errors.New("some error") 2684 }), 2685 wantErr: &SemanticError{action: "marshal", JSONKind: '"', GoType: marshalTextFuncType, Err: errors.New("some error")}, 2686 }, { 2687 name: name("Methods/Invalid/Text/UTF8"), 2688 in: marshalTextFunc(func() ([]byte, error) { 2689 return []byte("\xde\xad\xbe\xef"), nil 2690 }), 2691 wantErr: &SemanticError{action: "marshal", JSONKind: '"', GoType: marshalTextFuncType, Err: &SyntacticError{str: "invalid UTF-8 within string"}}, 2692 }, { 2693 name: name("Methods/Invalid/Text/SkipFunc"), 2694 in: marshalTextFunc(func() ([]byte, error) { 2695 return nil, SkipFunc 2696 }), 2697 wantErr: &SemanticError{action: "marshal", JSONKind: '"', GoType: marshalTextFuncType, Err: errors.New("marshal method cannot be skipped")}, 2698 }, { 2699 name: name("Methods/Invalid/MapKey/JSONv2/Syntax"), 2700 in: map[any]string{ 2701 addr(marshalJSONv2Func(func(mo MarshalOptions, enc *Encoder) error { 2702 return enc.WriteToken(Null) 2703 })): "invalid", 2704 }, 2705 want: `{`, 2706 wantErr: &SemanticError{action: "marshal", GoType: marshalJSONv2FuncType, Err: errMissingName}, 2707 }, { 2708 name: name("Methods/Invalid/MapKey/JSONv1/Syntax"), 2709 in: map[any]string{ 2710 addr(marshalJSONv1Func(func() ([]byte, error) { 2711 return []byte(`null`), nil 2712 })): "invalid", 2713 }, 2714 want: `{`, 2715 wantErr: &SemanticError{action: "marshal", JSONKind: 'n', GoType: marshalJSONv1FuncType, Err: errMissingName}, 2716 }, { 2717 name: name("Functions/Bool/V1"), 2718 mopts: MarshalOptions{ 2719 Marshalers: MarshalFuncV1(func(bool) ([]byte, error) { 2720 return []byte(`"called"`), nil 2721 }), 2722 }, 2723 in: true, 2724 want: `"called"`, 2725 }, { 2726 name: name("Functions/NamedBool/V1/NoMatch"), 2727 mopts: MarshalOptions{ 2728 Marshalers: MarshalFuncV1(func(namedBool) ([]byte, error) { 2729 return nil, errors.New("must not be called") 2730 }), 2731 }, 2732 in: true, 2733 want: `true`, 2734 }, { 2735 name: name("Functions/NamedBool/V1/Match"), 2736 mopts: MarshalOptions{ 2737 Marshalers: MarshalFuncV1(func(namedBool) ([]byte, error) { 2738 return []byte(`"called"`), nil 2739 }), 2740 }, 2741 in: namedBool(true), 2742 want: `"called"`, 2743 }, { 2744 name: name("Functions/PointerBool/V1/Match"), 2745 mopts: MarshalOptions{ 2746 Marshalers: MarshalFuncV1(func(v *bool) ([]byte, error) { 2747 _ = *v // must be a non-nil pointer 2748 return []byte(`"called"`), nil 2749 }), 2750 }, 2751 in: true, 2752 want: `"called"`, 2753 }, { 2754 name: name("Functions/Bool/V2"), 2755 mopts: MarshalOptions{ 2756 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v bool) error { 2757 return enc.WriteToken(String("called")) 2758 }), 2759 }, 2760 in: true, 2761 want: `"called"`, 2762 }, { 2763 name: name("Functions/NamedBool/V2/NoMatch"), 2764 mopts: MarshalOptions{ 2765 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v namedBool) error { 2766 return errors.New("must not be called") 2767 }), 2768 }, 2769 in: true, 2770 want: `true`, 2771 }, { 2772 name: name("Functions/NamedBool/V2/Match"), 2773 mopts: MarshalOptions{ 2774 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v namedBool) error { 2775 return enc.WriteToken(String("called")) 2776 }), 2777 }, 2778 in: namedBool(true), 2779 want: `"called"`, 2780 }, { 2781 name: name("Functions/PointerBool/V2/Match"), 2782 mopts: MarshalOptions{ 2783 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *bool) error { 2784 _ = *v // must be a non-nil pointer 2785 return enc.WriteToken(String("called")) 2786 }), 2787 }, 2788 in: true, 2789 want: `"called"`, 2790 }, { 2791 name: name("Functions/Bool/Empty1/NoMatch"), 2792 mopts: MarshalOptions{ 2793 Marshalers: new(Marshalers), 2794 }, 2795 in: true, 2796 want: `true`, 2797 }, { 2798 name: name("Functions/Bool/Empty2/NoMatch"), 2799 mopts: MarshalOptions{ 2800 Marshalers: NewMarshalers(), 2801 }, 2802 in: true, 2803 want: `true`, 2804 }, { 2805 name: name("Functions/Bool/V1/DirectError"), 2806 mopts: MarshalOptions{ 2807 Marshalers: MarshalFuncV1(func(bool) ([]byte, error) { 2808 return nil, errors.New("some error") 2809 }), 2810 }, 2811 in: true, 2812 wantErr: &SemanticError{action: "marshal", GoType: boolType, Err: errors.New("some error")}, 2813 }, { 2814 name: name("Functions/Bool/V1/SkipError"), 2815 mopts: MarshalOptions{ 2816 Marshalers: MarshalFuncV1(func(bool) ([]byte, error) { 2817 return nil, SkipFunc 2818 }), 2819 }, 2820 in: true, 2821 wantErr: &SemanticError{action: "marshal", GoType: boolType, Err: errors.New("marshal function of type func(T) ([]byte, error) cannot be skipped")}, 2822 }, { 2823 name: name("Functions/Bool/V1/InvalidValue"), 2824 mopts: MarshalOptions{ 2825 Marshalers: MarshalFuncV1(func(bool) ([]byte, error) { 2826 return []byte("invalid"), nil 2827 }), 2828 }, 2829 in: true, 2830 wantErr: &SemanticError{action: "marshal", JSONKind: 'i', GoType: boolType, Err: &SyntacticError{str: "invalid character 'i' at start of value"}}, 2831 }, { 2832 name: name("Functions/Bool/V2/DirectError"), 2833 mopts: MarshalOptions{ 2834 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v bool) error { 2835 return errors.New("some error") 2836 }), 2837 }, 2838 in: true, 2839 wantErr: &SemanticError{action: "marshal", GoType: boolType, Err: errors.New("some error")}, 2840 }, { 2841 name: name("Functions/Bool/V2/TooFew"), 2842 mopts: MarshalOptions{ 2843 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v bool) error { 2844 return nil 2845 }), 2846 }, 2847 in: true, 2848 wantErr: &SemanticError{action: "marshal", GoType: boolType, Err: errors.New("must write exactly one JSON value")}, 2849 }, { 2850 name: name("Functions/Bool/V2/TooMany"), 2851 mopts: MarshalOptions{ 2852 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v bool) error { 2853 enc.WriteValue([]byte(`"hello"`)) 2854 enc.WriteValue([]byte(`"world"`)) 2855 return nil 2856 }), 2857 }, 2858 in: true, 2859 want: `"hello""world"`, 2860 wantErr: &SemanticError{action: "marshal", GoType: boolType, Err: errors.New("must write exactly one JSON value")}, 2861 }, { 2862 name: name("Functions/Bool/V2/Skipped"), 2863 mopts: MarshalOptions{ 2864 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v bool) error { 2865 return SkipFunc 2866 }), 2867 }, 2868 in: true, 2869 want: `true`, 2870 }, { 2871 name: name("Functions/Bool/V2/ProcessBeforeSkip"), 2872 mopts: MarshalOptions{ 2873 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v bool) error { 2874 enc.WriteValue([]byte(`"hello"`)) 2875 return SkipFunc 2876 }), 2877 }, 2878 in: true, 2879 want: `"hello"`, 2880 wantErr: &SemanticError{action: "marshal", GoType: boolType, Err: errors.New("must not write any JSON tokens when skipping")}, 2881 }, { 2882 name: name("Functions/Bool/V2/WrappedSkipError"), 2883 mopts: MarshalOptions{ 2884 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v bool) error { 2885 return fmt.Errorf("wrap: %w", SkipFunc) 2886 }), 2887 }, 2888 in: true, 2889 wantErr: &SemanticError{action: "marshal", GoType: boolType, Err: fmt.Errorf("wrap: %w", SkipFunc)}, 2890 }, { 2891 name: name("Functions/Map/Key/NoCaseString/V1"), 2892 mopts: MarshalOptions{ 2893 Marshalers: MarshalFuncV1(func(v nocaseString) ([]byte, error) { 2894 return []byte(`"called"`), nil 2895 }), 2896 }, 2897 in: map[nocaseString]string{"hello": "world"}, 2898 want: `{"called":"world"}`, 2899 }, { 2900 name: name("Functions/Map/Key/PointerNoCaseString/V1"), 2901 mopts: MarshalOptions{ 2902 Marshalers: MarshalFuncV1(func(v *nocaseString) ([]byte, error) { 2903 _ = *v // must be a non-nil pointer 2904 return []byte(`"called"`), nil 2905 }), 2906 }, 2907 in: map[nocaseString]string{"hello": "world"}, 2908 want: `{"called":"world"}`, 2909 }, { 2910 name: name("Functions/Map/Key/TextMarshaler/V1"), 2911 mopts: MarshalOptions{ 2912 Marshalers: MarshalFuncV1(func(v encoding.TextMarshaler) ([]byte, error) { 2913 _ = *v.(*nocaseString) // must be a non-nil *nocaseString 2914 return []byte(`"called"`), nil 2915 }), 2916 }, 2917 in: map[nocaseString]string{"hello": "world"}, 2918 want: `{"called":"world"}`, 2919 }, { 2920 name: name("Functions/Map/Key/NoCaseString/V1/InvalidValue"), 2921 mopts: MarshalOptions{ 2922 Marshalers: MarshalFuncV1(func(v nocaseString) ([]byte, error) { 2923 return []byte(`null`), nil 2924 }), 2925 }, 2926 in: map[nocaseString]string{"hello": "world"}, 2927 want: `{`, 2928 wantErr: &SemanticError{action: "marshal", JSONKind: 'n', GoType: nocaseStringType, Err: errMissingName}, 2929 }, { 2930 name: name("Functions/Map/Key/NoCaseString/V2/InvalidKind"), 2931 mopts: MarshalOptions{ 2932 Marshalers: MarshalFuncV1(func(v nocaseString) ([]byte, error) { 2933 return []byte(`null`), nil 2934 }), 2935 }, 2936 in: map[nocaseString]string{"hello": "world"}, 2937 want: `{`, 2938 wantErr: &SemanticError{action: "marshal", JSONKind: 'n', GoType: nocaseStringType, Err: errMissingName}, 2939 }, { 2940 name: name("Functions/Map/Key/String/V1/DuplicateName"), 2941 mopts: MarshalOptions{ 2942 Marshalers: MarshalFuncV1(func(v string) ([]byte, error) { 2943 return []byte(`"name"`), nil 2944 }), 2945 }, 2946 in: map[string]string{"name1": "value", "name2": "value"}, 2947 want: `{"name":"name"`, 2948 wantErr: &SemanticError{action: "marshal", JSONKind: '"', GoType: stringType, Err: &SyntacticError{str: `duplicate name "name" in object`}}, 2949 }, { 2950 name: name("Functions/Map/Key/NoCaseString/V2"), 2951 mopts: MarshalOptions{ 2952 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v nocaseString) error { 2953 return enc.WriteValue([]byte(`"called"`)) 2954 }), 2955 }, 2956 in: map[nocaseString]string{"hello": "world"}, 2957 want: `{"called":"world"}`, 2958 }, { 2959 name: name("Functions/Map/Key/PointerNoCaseString/V2"), 2960 mopts: MarshalOptions{ 2961 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *nocaseString) error { 2962 _ = *v // must be a non-nil pointer 2963 return enc.WriteValue([]byte(`"called"`)) 2964 }), 2965 }, 2966 in: map[nocaseString]string{"hello": "world"}, 2967 want: `{"called":"world"}`, 2968 }, { 2969 name: name("Functions/Map/Key/TextMarshaler/V2"), 2970 mopts: MarshalOptions{ 2971 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v encoding.TextMarshaler) error { 2972 _ = *v.(*nocaseString) // must be a non-nil *nocaseString 2973 return enc.WriteValue([]byte(`"called"`)) 2974 }), 2975 }, 2976 in: map[nocaseString]string{"hello": "world"}, 2977 want: `{"called":"world"}`, 2978 }, { 2979 name: name("Functions/Map/Key/NoCaseString/V2/InvalidToken"), 2980 mopts: MarshalOptions{ 2981 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v nocaseString) error { 2982 return enc.WriteToken(Null) 2983 }), 2984 }, 2985 in: map[nocaseString]string{"hello": "world"}, 2986 want: `{`, 2987 wantErr: &SemanticError{action: "marshal", GoType: nocaseStringType, Err: errMissingName}, 2988 }, { 2989 name: name("Functions/Map/Key/NoCaseString/V2/InvalidValue"), 2990 mopts: MarshalOptions{ 2991 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v nocaseString) error { 2992 return enc.WriteValue([]byte(`null`)) 2993 }), 2994 }, 2995 in: map[nocaseString]string{"hello": "world"}, 2996 want: `{`, 2997 wantErr: &SemanticError{action: "marshal", GoType: nocaseStringType, Err: errMissingName}, 2998 }, { 2999 name: name("Functions/Map/Value/NoCaseString/V1"), 3000 mopts: MarshalOptions{ 3001 Marshalers: MarshalFuncV1(func(v nocaseString) ([]byte, error) { 3002 return []byte(`"called"`), nil 3003 }), 3004 }, 3005 in: map[string]nocaseString{"hello": "world"}, 3006 want: `{"hello":"called"}`, 3007 }, { 3008 name: name("Functions/Map/Value/PointerNoCaseString/V1"), 3009 mopts: MarshalOptions{ 3010 Marshalers: MarshalFuncV1(func(v *nocaseString) ([]byte, error) { 3011 _ = *v // must be a non-nil pointer 3012 return []byte(`"called"`), nil 3013 }), 3014 }, 3015 in: map[string]nocaseString{"hello": "world"}, 3016 want: `{"hello":"called"}`, 3017 }, { 3018 name: name("Functions/Map/Value/TextMarshaler/V1"), 3019 mopts: MarshalOptions{ 3020 Marshalers: MarshalFuncV1(func(v encoding.TextMarshaler) ([]byte, error) { 3021 _ = *v.(*nocaseString) // must be a non-nil *nocaseString 3022 return []byte(`"called"`), nil 3023 }), 3024 }, 3025 in: map[string]nocaseString{"hello": "world"}, 3026 want: `{"hello":"called"}`, 3027 }, { 3028 name: name("Functions/Map/Value/NoCaseString/V2"), 3029 mopts: MarshalOptions{ 3030 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v nocaseString) error { 3031 return enc.WriteValue([]byte(`"called"`)) 3032 }), 3033 }, 3034 in: map[string]nocaseString{"hello": "world"}, 3035 want: `{"hello":"called"}`, 3036 }, { 3037 name: name("Functions/Map/Value/PointerNoCaseString/V2"), 3038 mopts: MarshalOptions{ 3039 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *nocaseString) error { 3040 _ = *v // must be a non-nil pointer 3041 return enc.WriteValue([]byte(`"called"`)) 3042 }), 3043 }, 3044 in: map[string]nocaseString{"hello": "world"}, 3045 want: `{"hello":"called"}`, 3046 }, { 3047 name: name("Functions/Map/Value/TextMarshaler/V2"), 3048 mopts: MarshalOptions{ 3049 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v encoding.TextMarshaler) error { 3050 _ = *v.(*nocaseString) // must be a non-nil *nocaseString 3051 return enc.WriteValue([]byte(`"called"`)) 3052 }), 3053 }, 3054 in: map[string]nocaseString{"hello": "world"}, 3055 want: `{"hello":"called"}`, 3056 }, { 3057 name: name("Funtions/Struct/Fields"), 3058 mopts: MarshalOptions{ 3059 Marshalers: NewMarshalers( 3060 MarshalFuncV1(func(v bool) ([]byte, error) { 3061 return []byte(`"called1"`), nil 3062 }), 3063 MarshalFuncV1(func(v *string) ([]byte, error) { 3064 return []byte(`"called2"`), nil 3065 }), 3066 MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v []byte) error { 3067 return enc.WriteValue([]byte(`"called3"`)) 3068 }), 3069 MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *int64) error { 3070 return enc.WriteValue([]byte(`"called4"`)) 3071 }), 3072 ), 3073 }, 3074 in: structScalars{}, 3075 want: `{"Bool":"called1","String":"called2","Bytes":"called3","Int":"called4","Uint":0,"Float":0}`, 3076 }, { 3077 name: name("Functions/Struct/OmitEmpty"), 3078 mopts: MarshalOptions{ 3079 Marshalers: NewMarshalers( 3080 MarshalFuncV1(func(v bool) ([]byte, error) { 3081 return []byte(`null`), nil 3082 }), 3083 MarshalFuncV1(func(v string) ([]byte, error) { 3084 return []byte(`"called1"`), nil 3085 }), 3086 MarshalFuncV1(func(v *stringMarshalNonEmpty) ([]byte, error) { 3087 return []byte(`""`), nil 3088 }), 3089 MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v bytesMarshalNonEmpty) error { 3090 return enc.WriteValue([]byte(`{}`)) 3091 }), 3092 MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *float64) error { 3093 return enc.WriteValue([]byte(`[]`)) 3094 }), 3095 MarshalFuncV1(func(v mapMarshalNonEmpty) ([]byte, error) { 3096 return []byte(`"called2"`), nil 3097 }), 3098 MarshalFuncV1(func(v []string) ([]byte, error) { 3099 return []byte(`"called3"`), nil 3100 }), 3101 MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *sliceMarshalNonEmpty) error { 3102 return enc.WriteValue([]byte(`"called4"`)) 3103 }), 3104 ), 3105 }, 3106 in: structOmitEmptyAll{}, 3107 want: `{"String":"called1","MapNonEmpty":"called2","Slice":"called3","SliceNonEmpty":"called4"}`, 3108 }, { 3109 name: name("Functions/Struct/OmitZero"), 3110 mopts: MarshalOptions{ 3111 Marshalers: NewMarshalers( 3112 MarshalFuncV1(func(v bool) ([]byte, error) { 3113 panic("should not be called") 3114 }), 3115 MarshalFuncV1(func(v *string) ([]byte, error) { 3116 panic("should not be called") 3117 }), 3118 MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v []byte) error { 3119 panic("should not be called") 3120 }), 3121 MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *int64) error { 3122 panic("should not be called") 3123 }), 3124 ), 3125 }, 3126 in: structOmitZeroAll{}, 3127 want: `{}`, 3128 }, { 3129 name: name("Functions/Struct/Inlined"), 3130 mopts: MarshalOptions{ 3131 Marshalers: NewMarshalers( 3132 MarshalFuncV1(func(v structInlinedL1) ([]byte, error) { 3133 panic("should not be called") 3134 }), 3135 MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *StructEmbed2) error { 3136 panic("should not be called") 3137 }), 3138 ), 3139 }, 3140 in: structInlined{}, 3141 want: `{"D":""}`, 3142 }, { 3143 name: name("Functions/Slice/Elem"), 3144 mopts: MarshalOptions{ 3145 Marshalers: MarshalFuncV1(func(v bool) ([]byte, error) { 3146 return []byte(`"` + strconv.FormatBool(v) + `"`), nil 3147 }), 3148 }, 3149 in: []bool{true, false}, 3150 want: `["true","false"]`, 3151 }, { 3152 name: name("Functions/Array/Elem"), 3153 mopts: MarshalOptions{ 3154 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *bool) error { 3155 return enc.WriteValue([]byte(`"` + strconv.FormatBool(*v) + `"`)) 3156 }), 3157 }, 3158 in: [2]bool{true, false}, 3159 want: `["true","false"]`, 3160 }, { 3161 name: name("Functions/Pointer/Nil"), 3162 mopts: MarshalOptions{ 3163 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *bool) error { 3164 panic("should not be called") 3165 }), 3166 }, 3167 in: struct{ X *bool }{nil}, 3168 want: `{"X":null}`, 3169 }, { 3170 name: name("Functions/Pointer/NonNil"), 3171 mopts: MarshalOptions{ 3172 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *bool) error { 3173 return enc.WriteValue([]byte(`"called"`)) 3174 }), 3175 }, 3176 in: struct{ X *bool }{addr(false)}, 3177 want: `{"X":"called"}`, 3178 }, { 3179 name: name("Functions/Interface/Nil"), 3180 mopts: MarshalOptions{ 3181 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v fmt.Stringer) error { 3182 panic("should not be called") 3183 }), 3184 }, 3185 in: struct{ X fmt.Stringer }{nil}, 3186 want: `{"X":null}`, 3187 }, { 3188 name: name("Functions/Interface/NonNil/MatchInterface"), 3189 mopts: MarshalOptions{ 3190 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v fmt.Stringer) error { 3191 return enc.WriteValue([]byte(`"called"`)) 3192 }), 3193 }, 3194 in: struct{ X fmt.Stringer }{valueStringer{}}, 3195 want: `{"X":"called"}`, 3196 }, { 3197 name: name("Functions/Interface/NonNil/MatchConcrete"), 3198 mopts: MarshalOptions{ 3199 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v valueStringer) error { 3200 return enc.WriteValue([]byte(`"called"`)) 3201 }), 3202 }, 3203 in: struct{ X fmt.Stringer }{valueStringer{}}, 3204 want: `{"X":"called"}`, 3205 }, { 3206 name: name("Functions/Interface/NonNil/MatchPointer"), 3207 mopts: MarshalOptions{ 3208 Marshalers: MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *valueStringer) error { 3209 return enc.WriteValue([]byte(`"called"`)) 3210 }), 3211 }, 3212 in: struct{ X fmt.Stringer }{valueStringer{}}, 3213 want: `{"X":"called"}`, 3214 }, { 3215 name: name("Functions/Interface/Any"), 3216 in: []any{ 3217 nil, // nil 3218 valueStringer{}, // T 3219 (*valueStringer)(nil), // *T 3220 addr(valueStringer{}), // *T 3221 (**valueStringer)(nil), // **T 3222 addr((*valueStringer)(nil)), // **T 3223 addr(addr(valueStringer{})), // **T 3224 pointerStringer{}, // T 3225 (*pointerStringer)(nil), // *T 3226 addr(pointerStringer{}), // *T 3227 (**pointerStringer)(nil), // **T 3228 addr((*pointerStringer)(nil)), // **T 3229 addr(addr(pointerStringer{})), // **T 3230 "LAST", 3231 }, 3232 want: `[null,{},null,{},null,null,{},{},null,{},null,null,{},"LAST"]`, 3233 mopts: MarshalOptions{ 3234 Marshalers: func() *Marshalers { 3235 type P [2]int 3236 type PV struct { 3237 P P 3238 V any 3239 } 3240 3241 var lastChecks []func() error 3242 checkLast := func() error { 3243 for _, fn := range lastChecks { 3244 if err := fn(); err != nil { 3245 return err 3246 } 3247 } 3248 return SkipFunc 3249 } 3250 makeValueChecker := func(name string, want []PV) func(e *Encoder, v any) error { 3251 checkNext := func(e *Encoder, v any) error { 3252 p := P{len(e.tokens.stack), e.tokens.last.length()} 3253 rv := reflect.ValueOf(v) 3254 pv := PV{p, v} 3255 switch { 3256 case len(want) == 0: 3257 return fmt.Errorf("%s: %v: got more values than expected", name, p) 3258 case !rv.IsValid() || rv.Kind() != reflect.Pointer || rv.IsNil(): 3259 return fmt.Errorf("%s: %v: got %#v, want non-nil pointer type", name, p, v) 3260 case !reflect.DeepEqual(pv, want[0]): 3261 return fmt.Errorf("%s:\n\tgot %#v\n\twant %#v", name, pv, want[0]) 3262 default: 3263 want = want[1:] 3264 return SkipFunc 3265 } 3266 } 3267 lastChecks = append(lastChecks, func() error { 3268 if len(want) > 0 { 3269 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want)) 3270 } 3271 return nil 3272 }) 3273 return checkNext 3274 } 3275 makePositionChecker := func(name string, want []P) func(e *Encoder, v any) error { 3276 checkNext := func(e *Encoder, v any) error { 3277 p := P{len(e.tokens.stack), e.tokens.last.length()} 3278 switch { 3279 case len(want) == 0: 3280 return fmt.Errorf("%s: %v: got more values than wanted", name, p) 3281 case p != want[0]: 3282 return fmt.Errorf("%s: got %v, want %v", name, p, want[0]) 3283 default: 3284 want = want[1:] 3285 return SkipFunc 3286 } 3287 } 3288 lastChecks = append(lastChecks, func() error { 3289 if len(want) > 0 { 3290 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want)) 3291 } 3292 return nil 3293 }) 3294 return checkNext 3295 } 3296 3297 wantAny := []PV{ 3298 {P{0, 0}, addr([]any{ 3299 nil, 3300 valueStringer{}, 3301 (*valueStringer)(nil), 3302 addr(valueStringer{}), 3303 (**valueStringer)(nil), 3304 addr((*valueStringer)(nil)), 3305 addr(addr(valueStringer{})), 3306 pointerStringer{}, 3307 (*pointerStringer)(nil), 3308 addr(pointerStringer{}), 3309 (**pointerStringer)(nil), 3310 addr((*pointerStringer)(nil)), 3311 addr(addr(pointerStringer{})), 3312 "LAST", 3313 })}, 3314 {P{1, 0}, addr(any(nil))}, 3315 {P{1, 1}, addr(any(valueStringer{}))}, 3316 {P{1, 1}, addr(valueStringer{})}, 3317 {P{1, 2}, addr(any((*valueStringer)(nil)))}, 3318 {P{1, 2}, addr((*valueStringer)(nil))}, 3319 {P{1, 3}, addr(any(addr(valueStringer{})))}, 3320 {P{1, 3}, addr(addr(valueStringer{}))}, 3321 {P{1, 3}, addr(valueStringer{})}, 3322 {P{1, 4}, addr(any((**valueStringer)(nil)))}, 3323 {P{1, 4}, addr((**valueStringer)(nil))}, 3324 {P{1, 5}, addr(any(addr((*valueStringer)(nil))))}, 3325 {P{1, 5}, addr(addr((*valueStringer)(nil)))}, 3326 {P{1, 5}, addr((*valueStringer)(nil))}, 3327 {P{1, 6}, addr(any(addr(addr(valueStringer{}))))}, 3328 {P{1, 6}, addr(addr(addr(valueStringer{})))}, 3329 {P{1, 6}, addr(addr(valueStringer{}))}, 3330 {P{1, 6}, addr(valueStringer{})}, 3331 {P{1, 7}, addr(any(pointerStringer{}))}, 3332 {P{1, 7}, addr(pointerStringer{})}, 3333 {P{1, 8}, addr(any((*pointerStringer)(nil)))}, 3334 {P{1, 8}, addr((*pointerStringer)(nil))}, 3335 {P{1, 9}, addr(any(addr(pointerStringer{})))}, 3336 {P{1, 9}, addr(addr(pointerStringer{}))}, 3337 {P{1, 9}, addr(pointerStringer{})}, 3338 {P{1, 10}, addr(any((**pointerStringer)(nil)))}, 3339 {P{1, 10}, addr((**pointerStringer)(nil))}, 3340 {P{1, 11}, addr(any(addr((*pointerStringer)(nil))))}, 3341 {P{1, 11}, addr(addr((*pointerStringer)(nil)))}, 3342 {P{1, 11}, addr((*pointerStringer)(nil))}, 3343 {P{1, 12}, addr(any(addr(addr(pointerStringer{}))))}, 3344 {P{1, 12}, addr(addr(addr(pointerStringer{})))}, 3345 {P{1, 12}, addr(addr(pointerStringer{}))}, 3346 {P{1, 12}, addr(pointerStringer{})}, 3347 {P{1, 13}, addr(any("LAST"))}, 3348 {P{1, 13}, addr("LAST")}, 3349 } 3350 checkAny := makeValueChecker("any", wantAny) 3351 anyMarshaler := MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v any) error { 3352 return checkAny(enc, v) 3353 }) 3354 3355 var wantPointerAny []PV 3356 for _, v := range wantAny { 3357 if _, ok := v.V.(*any); ok { 3358 wantPointerAny = append(wantPointerAny, v) 3359 } 3360 } 3361 checkPointerAny := makeValueChecker("*any", wantPointerAny) 3362 pointerAnyMarshaler := MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *any) error { 3363 return checkPointerAny(enc, v) 3364 }) 3365 3366 checkNamedAny := makeValueChecker("namedAny", wantAny) 3367 namedAnyMarshaler := MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v namedAny) error { 3368 return checkNamedAny(enc, v) 3369 }) 3370 3371 checkPointerNamedAny := makeValueChecker("*namedAny", nil) 3372 pointerNamedAnyMarshaler := MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *namedAny) error { 3373 return checkPointerNamedAny(enc, v) 3374 }) 3375 3376 type stringer = fmt.Stringer 3377 var wantStringer []PV 3378 for _, v := range wantAny { 3379 if _, ok := v.V.(stringer); ok { 3380 wantStringer = append(wantStringer, v) 3381 } 3382 } 3383 checkStringer := makeValueChecker("stringer", wantStringer) 3384 stringerMarshaler := MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v stringer) error { 3385 return checkStringer(enc, v) 3386 }) 3387 3388 checkPointerStringer := makeValueChecker("*stringer", nil) 3389 pointerStringerMarshaler := MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *stringer) error { 3390 return checkPointerStringer(enc, v) 3391 }) 3392 3393 wantValueStringer := []P{{1, 1}, {1, 3}, {1, 6}} 3394 checkValueValueStringer := makePositionChecker("valueStringer", wantValueStringer) 3395 valueValueStringerMarshaler := MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v valueStringer) error { 3396 return checkValueValueStringer(enc, v) 3397 }) 3398 3399 checkPointerValueStringer := makePositionChecker("*valueStringer", wantValueStringer) 3400 pointerValueStringerMarshaler := MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *valueStringer) error { 3401 return checkPointerValueStringer(enc, v) 3402 }) 3403 3404 wantPointerStringer := []P{{1, 7}, {1, 9}, {1, 12}} 3405 checkValuePointerStringer := makePositionChecker("pointerStringer", wantPointerStringer) 3406 valuePointerStringerMarshaler := MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v pointerStringer) error { 3407 return checkValuePointerStringer(enc, v) 3408 }) 3409 3410 checkPointerPointerStringer := makePositionChecker("*pointerStringer", wantPointerStringer) 3411 pointerPointerStringerMarshaler := MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v *pointerStringer) error { 3412 return checkPointerPointerStringer(enc, v) 3413 }) 3414 3415 lastMarshaler := MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v string) error { 3416 return checkLast() 3417 }) 3418 3419 return NewMarshalers( 3420 anyMarshaler, 3421 pointerAnyMarshaler, 3422 namedAnyMarshaler, 3423 pointerNamedAnyMarshaler, // never called 3424 stringerMarshaler, 3425 pointerStringerMarshaler, // never called 3426 valueValueStringerMarshaler, 3427 pointerValueStringerMarshaler, 3428 valuePointerStringerMarshaler, 3429 pointerPointerStringerMarshaler, 3430 lastMarshaler, 3431 ) 3432 }(), 3433 }, 3434 }, { 3435 name: name("Functions/Precedence/V1First"), 3436 mopts: MarshalOptions{ 3437 Marshalers: NewMarshalers( 3438 MarshalFuncV1(func(bool) ([]byte, error) { 3439 return []byte(`"called"`), nil 3440 }), 3441 MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v bool) error { 3442 panic("should not be called") 3443 }), 3444 ), 3445 }, 3446 in: true, 3447 want: `"called"`, 3448 }, { 3449 name: name("Functions/Precedence/V2First"), 3450 mopts: MarshalOptions{ 3451 Marshalers: NewMarshalers( 3452 MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v bool) error { 3453 return enc.WriteToken(String("called")) 3454 }), 3455 MarshalFuncV1(func(bool) ([]byte, error) { 3456 panic("should not be called") 3457 }), 3458 ), 3459 }, 3460 in: true, 3461 want: `"called"`, 3462 }, { 3463 name: name("Functions/Precedence/V2Skipped"), 3464 mopts: MarshalOptions{ 3465 Marshalers: NewMarshalers( 3466 MarshalFuncV2(func(mo MarshalOptions, enc *Encoder, v bool) error { 3467 return SkipFunc 3468 }), 3469 MarshalFuncV1(func(bool) ([]byte, error) { 3470 return []byte(`"called"`), nil 3471 }), 3472 ), 3473 }, 3474 in: true, 3475 want: `"called"`, 3476 }, { 3477 name: name("Functions/Precedence/NestedFirst"), 3478 mopts: MarshalOptions{ 3479 Marshalers: NewMarshalers( 3480 NewMarshalers( 3481 MarshalFuncV1(func(bool) ([]byte, error) { 3482 return []byte(`"called"`), nil 3483 }), 3484 ), 3485 MarshalFuncV1(func(bool) ([]byte, error) { 3486 panic("should not be called") 3487 }), 3488 ), 3489 }, 3490 in: true, 3491 want: `"called"`, 3492 }, { 3493 name: name("Functions/Precedence/NestedLast"), 3494 mopts: MarshalOptions{ 3495 Marshalers: NewMarshalers( 3496 MarshalFuncV1(func(bool) ([]byte, error) { 3497 return []byte(`"called"`), nil 3498 }), 3499 NewMarshalers( 3500 MarshalFuncV1(func(bool) ([]byte, error) { 3501 panic("should not be called") 3502 }), 3503 ), 3504 ), 3505 }, 3506 in: true, 3507 want: `"called"`, 3508 }, { 3509 name: name("Duration/Zero"), 3510 in: struct { 3511 D1 time.Duration 3512 D2 time.Duration `json:",format:nanos"` 3513 }{0, 0}, 3514 want: `{"D1":"0s","D2":0}`, 3515 }, { 3516 name: name("Duration/Positive"), 3517 in: struct { 3518 D1 time.Duration 3519 D2 time.Duration `json:",format:nanos"` 3520 }{ 3521 123456789123456789, 3522 123456789123456789, 3523 }, 3524 want: `{"D1":"34293h33m9.123456789s","D2":123456789123456789}`, 3525 }, { 3526 name: name("Duration/Negative"), 3527 in: struct { 3528 D1 time.Duration 3529 D2 time.Duration `json:",format:nanos"` 3530 }{ 3531 -123456789123456789, 3532 -123456789123456789, 3533 }, 3534 want: `{"D1":"-34293h33m9.123456789s","D2":-123456789123456789}`, 3535 }, { 3536 name: name("Duration/Nanos/String"), 3537 in: struct { 3538 D1 time.Duration `json:",string,format:nanos"` 3539 D2 time.Duration `json:",string,format:nanos"` 3540 D3 time.Duration `json:",string,format:nanos"` 3541 }{ 3542 math.MinInt64, 3543 0, 3544 math.MaxInt64, 3545 }, 3546 want: `{"D1":"-9223372036854775808","D2":"0","D3":"9223372036854775807"}`, 3547 }, { 3548 name: name("Duration/Format/Invalid"), 3549 in: struct { 3550 D time.Duration `json:",format:invalid"` 3551 }{}, 3552 want: `{"D"`, 3553 wantErr: &SemanticError{action: "marshal", GoType: timeDurationType, Err: errors.New(`invalid format flag: "invalid"`)}, 3554 }, { 3555 name: name("Duration/IgnoreInvalidFormat"), 3556 mopts: MarshalOptions{formatDepth: 1000, format: "invalid"}, 3557 in: time.Duration(0), 3558 want: `"0s"`, 3559 }, { 3560 name: name("Time/Zero"), 3561 in: struct { 3562 T1 time.Time 3563 T2 time.Time `json:",format:RFC822"` 3564 T3 time.Time `json:",format:'2006-01-02'"` 3565 T4 time.Time `json:",omitzero"` 3566 T5 time.Time `json:",omitempty"` 3567 }{ 3568 time.Time{}, 3569 time.Time{}, 3570 time.Time{}, 3571 // This is zero according to time.Time.IsZero, 3572 // but non-zero according to reflect.Value.IsZero. 3573 time.Date(1, 1, 1, 0, 0, 0, 0, time.FixedZone("UTC", 0)), 3574 time.Time{}, 3575 }, 3576 want: `{"T1":"0001-01-01T00:00:00Z","T2":"01 Jan 01 00:00 UTC","T3":"0001-01-01","T5":"0001-01-01T00:00:00Z"}`, 3577 }, { 3578 name: name("Time/Format"), 3579 eopts: EncodeOptions{Indent: "\t"}, 3580 in: structTimeFormat{ 3581 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3582 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3583 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3584 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3585 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3586 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3587 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3588 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3589 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3590 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3591 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3592 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3593 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3594 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3595 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3596 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3597 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3598 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC), 3599 }, 3600 want: `{ 3601 "T1": "1234-01-02T03:04:05.000000006Z", 3602 "T2": "Mon Jan 2 03:04:05 1234", 3603 "T3": "Mon Jan 2 03:04:05 UTC 1234", 3604 "T4": "Mon Jan 02 03:04:05 +0000 1234", 3605 "T5": "02 Jan 34 03:04 UTC", 3606 "T6": "02 Jan 34 03:04 +0000", 3607 "T7": "Monday, 02-Jan-34 03:04:05 UTC", 3608 "T8": "Mon, 02 Jan 1234 03:04:05 UTC", 3609 "T9": "Mon, 02 Jan 1234 03:04:05 +0000", 3610 "T10": "1234-01-02T03:04:05Z", 3611 "T11": "1234-01-02T03:04:05.000000006Z", 3612 "T12": "3:04AM", 3613 "T13": "Jan 2 03:04:05", 3614 "T14": "Jan 2 03:04:05.000", 3615 "T15": "Jan 2 03:04:05.000000", 3616 "T16": "Jan 2 03:04:05.000000006", 3617 "T17": "1234-01-02", 3618 "T18": "\"weird\"1234" 3619 }`, 3620 }, { 3621 name: name("Time/Format/Invalid"), 3622 in: struct { 3623 T time.Time `json:",format:UndefinedConstant"` 3624 }{}, 3625 want: `{"T"`, 3626 wantErr: &SemanticError{action: "marshal", GoType: timeTimeType, Err: errors.New(`undefined format layout: UndefinedConstant`)}, 3627 }, { 3628 name: name("Time/Format/YearOverflow"), 3629 in: struct { 3630 T1 time.Time 3631 T2 time.Time 3632 }{ 3633 time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second), 3634 time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC), 3635 }, 3636 want: `{"T1":"9999-12-31T23:59:59Z","T2"`, 3637 wantErr: &SemanticError{action: "marshal", GoType: timeTimeType, Err: errors.New(`year outside of range [0,9999]`)}, 3638 }, { 3639 name: name("Time/Format/YearUnderflow"), 3640 in: struct { 3641 T1 time.Time 3642 T2 time.Time 3643 }{ 3644 time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC), 3645 time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second), 3646 }, 3647 want: `{"T1":"0000-01-01T00:00:00Z","T2"`, 3648 wantErr: &SemanticError{action: "marshal", GoType: timeTimeType, Err: errors.New(`year outside of range [0,9999]`)}, 3649 }, { 3650 name: name("Time/Format/YearUnderflow"), 3651 in: struct{ T time.Time }{time.Date(-998, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second)}, 3652 want: `{"T"`, 3653 wantErr: &SemanticError{action: "marshal", GoType: timeTimeType, Err: errors.New(`year outside of range [0,9999]`)}, 3654 }, { 3655 name: name("Time/Format/ZoneExact"), 3656 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 23*60*60+59*60))}, 3657 want: `{"T":"2020-01-01T00:00:00+23:59"}`, 3658 }, { 3659 name: name("Time/Format/ZoneHourOverflow"), 3660 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 24*60*60))}, 3661 want: `{"T"`, 3662 wantErr: &SemanticError{action: "marshal", GoType: timeTimeType, Err: errors.New(`timezone hour outside of range [0,23]`)}, 3663 }, { 3664 name: name("Time/Format/ZoneHourOverflow"), 3665 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 123*60*60))}, 3666 want: `{"T"`, 3667 wantErr: &SemanticError{action: "marshal", GoType: timeTimeType, Err: errors.New(`timezone hour outside of range [0,23]`)}, 3668 }, { 3669 name: name("Time/IgnoreInvalidFormat"), 3670 mopts: MarshalOptions{formatDepth: 1000, format: "invalid"}, 3671 in: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), 3672 want: `"2000-01-01T00:00:00Z"`, 3673 }} 3674 3675 for _, tt := range tests { 3676 t.Run(tt.name.name, func(t *testing.T) { 3677 var got []byte 3678 var gotErr error 3679 if tt.useWriter { 3680 bb := new(struct{ bytes.Buffer }) // avoid optimizations with bytes.Buffer 3681 gotErr = tt.mopts.MarshalFull(tt.eopts, bb, tt.in) 3682 got = bb.Bytes() 3683 } else { 3684 got, gotErr = tt.mopts.Marshal(tt.eopts, tt.in) 3685 } 3686 if tt.canonicalize { 3687 (*RawValue)(&got).Canonicalize() 3688 } 3689 if string(got) != tt.want { 3690 t.Errorf("%s: Marshal output mismatch:\ngot %s\nwant %s", tt.name.where, got, tt.want) 3691 } 3692 if !reflect.DeepEqual(gotErr, tt.wantErr) { 3693 t.Errorf("%s: Marshal error mismatch:\ngot %v\nwant %v", tt.name.where, gotErr, tt.wantErr) 3694 } 3695 }) 3696 } 3697 } 3698 3699 func TestUnmarshal(t *testing.T) { 3700 tests := []struct { 3701 name testName 3702 dopts DecodeOptions 3703 uopts UnmarshalOptions 3704 inBuf string 3705 inVal any 3706 want any 3707 wantErr error 3708 }{{ 3709 name: name("Nil"), 3710 inBuf: `null`, 3711 wantErr: &SemanticError{action: "unmarshal", Err: errors.New("value must be passed as a non-nil pointer reference")}, 3712 }, { 3713 name: name("NilPointer"), 3714 inBuf: `null`, 3715 inVal: (*string)(nil), 3716 want: (*string)(nil), 3717 wantErr: &SemanticError{action: "unmarshal", GoType: stringType, Err: errors.New("value must be passed as a non-nil pointer reference")}, 3718 }, { 3719 name: name("NonPointer"), 3720 inBuf: `null`, 3721 inVal: "unchanged", 3722 want: "unchanged", 3723 wantErr: &SemanticError{action: "unmarshal", GoType: stringType, Err: errors.New("value must be passed as a non-nil pointer reference")}, 3724 }, { 3725 name: name("Bools/TrailingJunk"), 3726 inBuf: `falsetrue`, 3727 inVal: addr(true), 3728 want: addr(false), 3729 wantErr: newInvalidCharacterError([]byte("t"), "after top-level value"), 3730 }, { 3731 name: name("Bools/Null"), 3732 inBuf: `null`, 3733 inVal: addr(true), 3734 want: addr(false), 3735 }, { 3736 name: name("Bools"), 3737 inBuf: `[null,false,true]`, 3738 inVal: new([]bool), 3739 want: addr([]bool{false, false, true}), 3740 }, { 3741 name: name("Bools/Named"), 3742 inBuf: `[null,false,true]`, 3743 inVal: new([]namedBool), 3744 want: addr([]namedBool{false, false, true}), 3745 }, { 3746 name: name("Bools/Invalid/StringifiedFalse"), 3747 uopts: UnmarshalOptions{StringifyNumbers: true}, 3748 inBuf: `"false"`, 3749 inVal: addr(true), 3750 want: addr(true), 3751 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: boolType}, 3752 }, { 3753 name: name("Bools/Invalid/StringifiedTrue"), 3754 uopts: UnmarshalOptions{StringifyNumbers: true}, 3755 inBuf: `"true"`, 3756 inVal: addr(true), 3757 want: addr(true), 3758 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: boolType}, 3759 }, { 3760 name: name("Bools/Invalid/Number"), 3761 inBuf: `0`, 3762 inVal: addr(true), 3763 want: addr(true), 3764 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: boolType}, 3765 }, { 3766 name: name("Bools/Invalid/String"), 3767 inBuf: `""`, 3768 inVal: addr(true), 3769 want: addr(true), 3770 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: boolType}, 3771 }, { 3772 name: name("Bools/Invalid/Object"), 3773 inBuf: `{}`, 3774 inVal: addr(true), 3775 want: addr(true), 3776 wantErr: &SemanticError{action: "unmarshal", JSONKind: '{', GoType: boolType}, 3777 }, { 3778 name: name("Bools/Invalid/Array"), 3779 inBuf: `[]`, 3780 inVal: addr(true), 3781 want: addr(true), 3782 wantErr: &SemanticError{action: "unmarshal", JSONKind: '[', GoType: boolType}, 3783 }, { 3784 name: name("Bools/IgnoreInvalidFormat"), 3785 uopts: UnmarshalOptions{formatDepth: 1000, format: "invalid"}, 3786 inBuf: `false`, 3787 inVal: addr(true), 3788 want: addr(false), 3789 }, { 3790 name: name("Strings/Null"), 3791 inBuf: `null`, 3792 inVal: addr("something"), 3793 want: addr(""), 3794 }, { 3795 name: name("Strings"), 3796 inBuf: `[null,"","hello","世界"]`, 3797 inVal: new([]string), 3798 want: addr([]string{"", "", "hello", "世界"}), 3799 }, { 3800 name: name("Strings/Escaped"), 3801 inBuf: `[null,"","\u0068\u0065\u006c\u006c\u006f","\u4e16\u754c"]`, 3802 inVal: new([]string), 3803 want: addr([]string{"", "", "hello", "世界"}), 3804 }, { 3805 name: name("Strings/Named"), 3806 inBuf: `[null,"","hello","世界"]`, 3807 inVal: new([]namedString), 3808 want: addr([]namedString{"", "", "hello", "世界"}), 3809 }, { 3810 name: name("Strings/Invalid/False"), 3811 inBuf: `false`, 3812 inVal: addr("nochange"), 3813 want: addr("nochange"), 3814 wantErr: &SemanticError{action: "unmarshal", JSONKind: 'f', GoType: stringType}, 3815 }, { 3816 name: name("Strings/Invalid/True"), 3817 inBuf: `true`, 3818 inVal: addr("nochange"), 3819 want: addr("nochange"), 3820 wantErr: &SemanticError{action: "unmarshal", JSONKind: 't', GoType: stringType}, 3821 }, { 3822 name: name("Strings/Invalid/Object"), 3823 inBuf: `{}`, 3824 inVal: addr("nochange"), 3825 want: addr("nochange"), 3826 wantErr: &SemanticError{action: "unmarshal", JSONKind: '{', GoType: stringType}, 3827 }, { 3828 name: name("Strings/Invalid/Array"), 3829 inBuf: `[]`, 3830 inVal: addr("nochange"), 3831 want: addr("nochange"), 3832 wantErr: &SemanticError{action: "unmarshal", JSONKind: '[', GoType: stringType}, 3833 }, { 3834 name: name("Strings/IgnoreInvalidFormat"), 3835 uopts: UnmarshalOptions{formatDepth: 1000, format: "invalid"}, 3836 inBuf: `"hello"`, 3837 inVal: addr("goodbye"), 3838 want: addr("hello"), 3839 }, { 3840 name: name("Bytes/Null"), 3841 inBuf: `null`, 3842 inVal: addr([]byte("something")), 3843 want: addr([]byte(nil)), 3844 }, { 3845 name: name("Bytes"), 3846 inBuf: `[null,"","AQ==","AQI=","AQID"]`, 3847 inVal: new([][]byte), 3848 want: addr([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}), 3849 }, { 3850 name: name("Bytes/Large"), 3851 inBuf: `"dGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cgYW5kIGF0ZSB0aGUgaG9tZXdvcmsgdGhhdCBJIHNwZW50IHNvIG11Y2ggdGltZSBvbi4="`, 3852 inVal: new([]byte), 3853 want: addr([]byte("the quick brown fox jumped over the lazy dog and ate the homework that I spent so much time on.")), 3854 }, { 3855 name: name("Bytes/Reuse"), 3856 inBuf: `"AQID"`, 3857 inVal: addr([]byte("changed")), 3858 want: addr([]byte{1, 2, 3}), 3859 }, { 3860 name: name("Bytes/Escaped"), 3861 inBuf: `[null,"","\u0041\u0051\u003d\u003d","\u0041\u0051\u0049\u003d","\u0041\u0051\u0049\u0044"]`, 3862 inVal: new([][]byte), 3863 want: addr([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}), 3864 }, { 3865 name: name("Bytes/Named"), 3866 inBuf: `[null,"","AQ==","AQI=","AQID"]`, 3867 inVal: new([]namedBytes), 3868 want: addr([]namedBytes{nil, {}, {1}, {1, 2}, {1, 2, 3}}), 3869 }, { 3870 name: name("Bytes/NotStringified"), 3871 uopts: UnmarshalOptions{StringifyNumbers: true}, 3872 inBuf: `[null,"","AQ==","AQI=","AQID"]`, 3873 inVal: new([][]byte), 3874 want: addr([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}), 3875 }, { 3876 // NOTE: []namedByte is not assignable to []byte, 3877 // so the following should be treated as a slice of uints. 3878 name: name("Bytes/Invariant"), 3879 inBuf: `[null,[],[1],[1,2],[1,2,3]]`, 3880 inVal: new([][]namedByte), 3881 want: addr([][]namedByte{nil, {}, {1}, {1, 2}, {1, 2, 3}}), 3882 }, { 3883 // NOTE: This differs in behavior from v1, 3884 // but keeps the representation of slices and arrays more consistent. 3885 name: name("Bytes/ByteArray"), 3886 inBuf: `"aGVsbG8="`, 3887 inVal: new([5]byte), 3888 want: addr([5]byte{'h', 'e', 'l', 'l', 'o'}), 3889 }, { 3890 name: name("Bytes/ByteArray0/Valid"), 3891 inBuf: `""`, 3892 inVal: new([0]byte), 3893 want: addr([0]byte{}), 3894 }, { 3895 name: name("Bytes/ByteArray0/Invalid"), 3896 inBuf: `"A"`, 3897 inVal: new([0]byte), 3898 want: addr([0]byte{}), 3899 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array0ByteType, Err: func() error { 3900 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("A")) 3901 return err 3902 }()}, 3903 }, { 3904 name: name("Bytes/ByteArray0/Overflow"), 3905 inBuf: `"AA=="`, 3906 inVal: new([0]byte), 3907 want: addr([0]byte{}), 3908 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array0ByteType, Err: errors.New("decoded base64 length of 1 mismatches array length of 0")}, 3909 }, { 3910 name: name("Bytes/ByteArray1/Valid"), 3911 inBuf: `"AQ=="`, 3912 inVal: new([1]byte), 3913 want: addr([1]byte{1}), 3914 }, { 3915 name: name("Bytes/ByteArray1/Invalid"), 3916 inBuf: `"$$=="`, 3917 inVal: new([1]byte), 3918 want: addr([1]byte{}), 3919 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array1ByteType, Err: func() error { 3920 _, err := base64.StdEncoding.Decode(make([]byte, 1), []byte("$$==")) 3921 return err 3922 }()}, 3923 }, { 3924 name: name("Bytes/ByteArray1/Underflow"), 3925 inBuf: `""`, 3926 inVal: new([1]byte), 3927 want: addr([1]byte{}), 3928 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array1ByteType, Err: errors.New("decoded base64 length of 0 mismatches array length of 1")}, 3929 }, { 3930 name: name("Bytes/ByteArray1/Overflow"), 3931 inBuf: `"AQI="`, 3932 inVal: new([1]byte), 3933 want: addr([1]byte{}), 3934 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array1ByteType, Err: errors.New("decoded base64 length of 2 mismatches array length of 1")}, 3935 }, { 3936 name: name("Bytes/ByteArray2/Valid"), 3937 inBuf: `"AQI="`, 3938 inVal: new([2]byte), 3939 want: addr([2]byte{1, 2}), 3940 }, { 3941 name: name("Bytes/ByteArray2/Invalid"), 3942 inBuf: `"$$$="`, 3943 inVal: new([2]byte), 3944 want: addr([2]byte{}), 3945 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array2ByteType, Err: func() error { 3946 _, err := base64.StdEncoding.Decode(make([]byte, 2), []byte("$$$=")) 3947 return err 3948 }()}, 3949 }, { 3950 name: name("Bytes/ByteArray2/Underflow"), 3951 inBuf: `"AQ=="`, 3952 inVal: new([2]byte), 3953 want: addr([2]byte{}), 3954 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array2ByteType, Err: errors.New("decoded base64 length of 1 mismatches array length of 2")}, 3955 }, { 3956 name: name("Bytes/ByteArray2/Overflow"), 3957 inBuf: `"AQID"`, 3958 inVal: new([2]byte), 3959 want: addr([2]byte{}), 3960 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array2ByteType, Err: errors.New("decoded base64 length of 3 mismatches array length of 2")}, 3961 }, { 3962 name: name("Bytes/ByteArray3/Valid"), 3963 inBuf: `"AQID"`, 3964 inVal: new([3]byte), 3965 want: addr([3]byte{1, 2, 3}), 3966 }, { 3967 name: name("Bytes/ByteArray3/Invalid"), 3968 inBuf: `"$$$$"`, 3969 inVal: new([3]byte), 3970 want: addr([3]byte{}), 3971 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array3ByteType, Err: func() error { 3972 _, err := base64.StdEncoding.Decode(make([]byte, 3), []byte("$$$$")) 3973 return err 3974 }()}, 3975 }, { 3976 name: name("Bytes/ByteArray3/Underflow"), 3977 inBuf: `"AQI="`, 3978 inVal: new([3]byte), 3979 want: addr([3]byte{}), 3980 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array3ByteType, Err: errors.New("decoded base64 length of 2 mismatches array length of 3")}, 3981 }, { 3982 name: name("Bytes/ByteArray3/Overflow"), 3983 inBuf: `"AQIDAQ=="`, 3984 inVal: new([3]byte), 3985 want: addr([3]byte{}), 3986 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array3ByteType, Err: errors.New("decoded base64 length of 4 mismatches array length of 3")}, 3987 }, { 3988 name: name("Bytes/ByteArray4/Valid"), 3989 inBuf: `"AQIDBA=="`, 3990 inVal: new([4]byte), 3991 want: addr([4]byte{1, 2, 3, 4}), 3992 }, { 3993 name: name("Bytes/ByteArray4/Invalid"), 3994 inBuf: `"$$$$$$=="`, 3995 inVal: new([4]byte), 3996 want: addr([4]byte{}), 3997 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array4ByteType, Err: func() error { 3998 _, err := base64.StdEncoding.Decode(make([]byte, 4), []byte("$$$$$$==")) 3999 return err 4000 }()}, 4001 }, { 4002 name: name("Bytes/ByteArray4/Underflow"), 4003 inBuf: `"AQID"`, 4004 inVal: new([4]byte), 4005 want: addr([4]byte{}), 4006 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array4ByteType, Err: errors.New("decoded base64 length of 3 mismatches array length of 4")}, 4007 }, { 4008 name: name("Bytes/ByteArray4/Overflow"), 4009 inBuf: `"AQIDBAU="`, 4010 inVal: new([4]byte), 4011 want: addr([4]byte{}), 4012 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array4ByteType, Err: errors.New("decoded base64 length of 5 mismatches array length of 4")}, 4013 }, { 4014 // NOTE: []namedByte is not assignable to []byte, 4015 // so the following should be treated as a array of uints. 4016 name: name("Bytes/NamedByteArray"), 4017 inBuf: `[104,101,108,108,111]`, 4018 inVal: new([5]namedByte), 4019 want: addr([5]namedByte{'h', 'e', 'l', 'l', 'o'}), 4020 }, { 4021 name: name("Bytes/Valid/Denormalized"), 4022 inBuf: `"AR=="`, 4023 inVal: new([]byte), 4024 want: addr([]byte{1}), 4025 }, { 4026 name: name("Bytes/Invalid/Unpadded1"), 4027 inBuf: `"AQ="`, 4028 inVal: addr([]byte("nochange")), 4029 want: addr([]byte("nochange")), 4030 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: func() error { 4031 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("AQ=")) 4032 return err 4033 }()}, 4034 }, { 4035 name: name("Bytes/Invalid/Unpadded2"), 4036 inBuf: `"AQ"`, 4037 inVal: addr([]byte("nochange")), 4038 want: addr([]byte("nochange")), 4039 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: func() error { 4040 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("AQ")) 4041 return err 4042 }()}, 4043 }, { 4044 name: name("Bytes/Invalid/Character"), 4045 inBuf: `"@@@@"`, 4046 inVal: addr([]byte("nochange")), 4047 want: addr([]byte("nochange")), 4048 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: func() error { 4049 _, err := base64.StdEncoding.Decode(make([]byte, 3), []byte("@@@@")) 4050 return err 4051 }()}, 4052 }, { 4053 name: name("Bytes/Invalid/Bool"), 4054 inBuf: `true`, 4055 inVal: addr([]byte("nochange")), 4056 want: addr([]byte("nochange")), 4057 wantErr: &SemanticError{action: "unmarshal", JSONKind: 't', GoType: bytesType}, 4058 }, { 4059 name: name("Bytes/Invalid/Number"), 4060 inBuf: `0`, 4061 inVal: addr([]byte("nochange")), 4062 want: addr([]byte("nochange")), 4063 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: bytesType}, 4064 }, { 4065 name: name("Bytes/Invalid/Object"), 4066 inBuf: `{}`, 4067 inVal: addr([]byte("nochange")), 4068 want: addr([]byte("nochange")), 4069 wantErr: &SemanticError{action: "unmarshal", JSONKind: '{', GoType: bytesType}, 4070 }, { 4071 name: name("Bytes/Invalid/Array"), 4072 inBuf: `[]`, 4073 inVal: addr([]byte("nochange")), 4074 want: addr([]byte("nochange")), 4075 wantErr: &SemanticError{action: "unmarshal", JSONKind: '[', GoType: bytesType}, 4076 }, { 4077 name: name("Bytes/IgnoreInvalidFormat"), 4078 uopts: UnmarshalOptions{formatDepth: 1000, format: "invalid"}, 4079 inBuf: `"aGVsbG8="`, 4080 inVal: new([]byte), 4081 want: addr([]byte("hello")), 4082 }, { 4083 name: name("Ints/Null"), 4084 inBuf: `null`, 4085 inVal: addr(int(1)), 4086 want: addr(int(0)), 4087 }, { 4088 name: name("Ints/Int"), 4089 inBuf: `1`, 4090 inVal: addr(int(0)), 4091 want: addr(int(1)), 4092 }, { 4093 name: name("Ints/Int8/MinOverflow"), 4094 inBuf: `-129`, 4095 inVal: addr(int8(-1)), 4096 want: addr(int8(-1)), 4097 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: int8Type, Err: fmt.Errorf(`cannot parse "-129" as signed integer: %w`, strconv.ErrRange)}, 4098 }, { 4099 name: name("Ints/Int8/Min"), 4100 inBuf: `-128`, 4101 inVal: addr(int8(0)), 4102 want: addr(int8(-128)), 4103 }, { 4104 name: name("Ints/Int8/Max"), 4105 inBuf: `127`, 4106 inVal: addr(int8(0)), 4107 want: addr(int8(127)), 4108 }, { 4109 name: name("Ints/Int8/MaxOverflow"), 4110 inBuf: `128`, 4111 inVal: addr(int8(-1)), 4112 want: addr(int8(-1)), 4113 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: int8Type, Err: fmt.Errorf(`cannot parse "128" as signed integer: %w`, strconv.ErrRange)}, 4114 }, { 4115 name: name("Ints/Int16/MinOverflow"), 4116 inBuf: `-32769`, 4117 inVal: addr(int16(-1)), 4118 want: addr(int16(-1)), 4119 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: int16Type, Err: fmt.Errorf(`cannot parse "-32769" as signed integer: %w`, strconv.ErrRange)}, 4120 }, { 4121 name: name("Ints/Int16/Min"), 4122 inBuf: `-32768`, 4123 inVal: addr(int16(0)), 4124 want: addr(int16(-32768)), 4125 }, { 4126 name: name("Ints/Int16/Max"), 4127 inBuf: `32767`, 4128 inVal: addr(int16(0)), 4129 want: addr(int16(32767)), 4130 }, { 4131 name: name("Ints/Int16/MaxOverflow"), 4132 inBuf: `32768`, 4133 inVal: addr(int16(-1)), 4134 want: addr(int16(-1)), 4135 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: int16Type, Err: fmt.Errorf(`cannot parse "32768" as signed integer: %w`, strconv.ErrRange)}, 4136 }, { 4137 name: name("Ints/Int32/MinOverflow"), 4138 inBuf: `-2147483649`, 4139 inVal: addr(int32(-1)), 4140 want: addr(int32(-1)), 4141 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: int32Type, Err: fmt.Errorf(`cannot parse "-2147483649" as signed integer: %w`, strconv.ErrRange)}, 4142 }, { 4143 name: name("Ints/Int32/Min"), 4144 inBuf: `-2147483648`, 4145 inVal: addr(int32(0)), 4146 want: addr(int32(-2147483648)), 4147 }, { 4148 name: name("Ints/Int32/Max"), 4149 inBuf: `2147483647`, 4150 inVal: addr(int32(0)), 4151 want: addr(int32(2147483647)), 4152 }, { 4153 name: name("Ints/Int32/MaxOverflow"), 4154 inBuf: `2147483648`, 4155 inVal: addr(int32(-1)), 4156 want: addr(int32(-1)), 4157 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: int32Type, Err: fmt.Errorf(`cannot parse "2147483648" as signed integer: %w`, strconv.ErrRange)}, 4158 }, { 4159 name: name("Ints/Int64/MinOverflow"), 4160 inBuf: `-9223372036854775809`, 4161 inVal: addr(int64(-1)), 4162 want: addr(int64(-1)), 4163 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: int64Type, Err: fmt.Errorf(`cannot parse "-9223372036854775809" as signed integer: %w`, strconv.ErrRange)}, 4164 }, { 4165 name: name("Ints/Int64/Min"), 4166 inBuf: `-9223372036854775808`, 4167 inVal: addr(int64(0)), 4168 want: addr(int64(-9223372036854775808)), 4169 }, { 4170 name: name("Ints/Int64/Max"), 4171 inBuf: `9223372036854775807`, 4172 inVal: addr(int64(0)), 4173 want: addr(int64(9223372036854775807)), 4174 }, { 4175 name: name("Ints/Int64/MaxOverflow"), 4176 inBuf: `9223372036854775808`, 4177 inVal: addr(int64(-1)), 4178 want: addr(int64(-1)), 4179 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: int64Type, Err: fmt.Errorf(`cannot parse "9223372036854775808" as signed integer: %w`, strconv.ErrRange)}, 4180 }, { 4181 name: name("Ints/Named"), 4182 inBuf: `-6464`, 4183 inVal: addr(namedInt64(0)), 4184 want: addr(namedInt64(-6464)), 4185 }, { 4186 name: name("Ints/Stringified"), 4187 uopts: UnmarshalOptions{StringifyNumbers: true}, 4188 inBuf: `"-6464"`, 4189 inVal: new(int), 4190 want: addr(int(-6464)), 4191 }, { 4192 name: name("Ints/Escaped"), 4193 uopts: UnmarshalOptions{StringifyNumbers: true}, 4194 inBuf: `"\u002d\u0036\u0034\u0036\u0034"`, 4195 inVal: new(int), 4196 want: addr(int(-6464)), 4197 }, { 4198 name: name("Ints/Valid/NegativeZero"), 4199 inBuf: `-0`, 4200 inVal: addr(int(1)), 4201 want: addr(int(0)), 4202 }, { 4203 name: name("Ints/Invalid/Fraction"), 4204 inBuf: `1.0`, 4205 inVal: addr(int(-1)), 4206 want: addr(int(-1)), 4207 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: intType, Err: fmt.Errorf(`cannot parse "1.0" as signed integer: %w`, strconv.ErrSyntax)}, 4208 }, { 4209 name: name("Ints/Invalid/Exponent"), 4210 inBuf: `1e0`, 4211 inVal: addr(int(-1)), 4212 want: addr(int(-1)), 4213 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: intType, Err: fmt.Errorf(`cannot parse "1e0" as signed integer: %w`, strconv.ErrSyntax)}, 4214 }, { 4215 name: name("Ints/Invalid/StringifiedFraction"), 4216 uopts: UnmarshalOptions{StringifyNumbers: true}, 4217 inBuf: `"1.0"`, 4218 inVal: addr(int(-1)), 4219 want: addr(int(-1)), 4220 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: intType, Err: fmt.Errorf(`cannot parse "1.0" as signed integer: %w`, strconv.ErrSyntax)}, 4221 }, { 4222 name: name("Ints/Invalid/StringifiedExponent"), 4223 uopts: UnmarshalOptions{StringifyNumbers: true}, 4224 inBuf: `"1e0"`, 4225 inVal: addr(int(-1)), 4226 want: addr(int(-1)), 4227 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: intType, Err: fmt.Errorf(`cannot parse "1e0" as signed integer: %w`, strconv.ErrSyntax)}, 4228 }, { 4229 name: name("Ints/Invalid/Overflow"), 4230 inBuf: `100000000000000000000000000000`, 4231 inVal: addr(int(-1)), 4232 want: addr(int(-1)), 4233 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: intType, Err: fmt.Errorf(`cannot parse "100000000000000000000000000000" as signed integer: %w`, strconv.ErrRange)}, 4234 }, { 4235 name: name("Ints/Invalid/OverflowSyntax"), 4236 uopts: UnmarshalOptions{StringifyNumbers: true}, 4237 inBuf: `"100000000000000000000000000000x"`, 4238 inVal: addr(int(-1)), 4239 want: addr(int(-1)), 4240 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: intType, Err: fmt.Errorf(`cannot parse "100000000000000000000000000000x" as signed integer: %w`, strconv.ErrSyntax)}, 4241 }, { 4242 name: name("Ints/Invalid/Whitespace"), 4243 uopts: UnmarshalOptions{StringifyNumbers: true}, 4244 inBuf: `"0 "`, 4245 inVal: addr(int(-1)), 4246 want: addr(int(-1)), 4247 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: intType, Err: fmt.Errorf(`cannot parse "0 " as signed integer: %w`, strconv.ErrSyntax)}, 4248 }, { 4249 name: name("Ints/Invalid/Bool"), 4250 inBuf: `true`, 4251 inVal: addr(int(-1)), 4252 want: addr(int(-1)), 4253 wantErr: &SemanticError{action: "unmarshal", JSONKind: 't', GoType: intType}, 4254 }, { 4255 name: name("Ints/Invalid/String"), 4256 inBuf: `"0"`, 4257 inVal: addr(int(-1)), 4258 want: addr(int(-1)), 4259 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: intType}, 4260 }, { 4261 name: name("Ints/Invalid/Object"), 4262 inBuf: `{}`, 4263 inVal: addr(int(-1)), 4264 want: addr(int(-1)), 4265 wantErr: &SemanticError{action: "unmarshal", JSONKind: '{', GoType: intType}, 4266 }, { 4267 name: name("Ints/Invalid/Array"), 4268 inBuf: `[]`, 4269 inVal: addr(int(-1)), 4270 want: addr(int(-1)), 4271 wantErr: &SemanticError{action: "unmarshal", JSONKind: '[', GoType: intType}, 4272 }, { 4273 name: name("Ints/IgnoreInvalidFormat"), 4274 uopts: UnmarshalOptions{formatDepth: 1000, format: "invalid"}, 4275 inBuf: `1`, 4276 inVal: addr(int(0)), 4277 want: addr(int(1)), 4278 }, { 4279 name: name("Uints/Null"), 4280 inBuf: `null`, 4281 inVal: addr(uint(1)), 4282 want: addr(uint(0)), 4283 }, { 4284 name: name("Uints/Uint"), 4285 inBuf: `1`, 4286 inVal: addr(uint(0)), 4287 want: addr(uint(1)), 4288 }, { 4289 name: name("Uints/Uint8/Min"), 4290 inBuf: `0`, 4291 inVal: addr(uint8(1)), 4292 want: addr(uint8(0)), 4293 }, { 4294 name: name("Uints/Uint8/Max"), 4295 inBuf: `255`, 4296 inVal: addr(uint8(0)), 4297 want: addr(uint8(255)), 4298 }, { 4299 name: name("Uints/Uint8/MaxOverflow"), 4300 inBuf: `256`, 4301 inVal: addr(uint8(1)), 4302 want: addr(uint8(1)), 4303 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: uint8Type, Err: fmt.Errorf(`cannot parse "256" as unsigned integer: %w`, strconv.ErrRange)}, 4304 }, { 4305 name: name("Uints/Uint16/Min"), 4306 inBuf: `0`, 4307 inVal: addr(uint16(1)), 4308 want: addr(uint16(0)), 4309 }, { 4310 name: name("Uints/Uint16/Max"), 4311 inBuf: `65535`, 4312 inVal: addr(uint16(0)), 4313 want: addr(uint16(65535)), 4314 }, { 4315 name: name("Uints/Uint16/MaxOverflow"), 4316 inBuf: `65536`, 4317 inVal: addr(uint16(1)), 4318 want: addr(uint16(1)), 4319 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: uint16Type, Err: fmt.Errorf(`cannot parse "65536" as unsigned integer: %w`, strconv.ErrRange)}, 4320 }, { 4321 name: name("Uints/Uint32/Min"), 4322 inBuf: `0`, 4323 inVal: addr(uint32(1)), 4324 want: addr(uint32(0)), 4325 }, { 4326 name: name("Uints/Uint32/Max"), 4327 inBuf: `4294967295`, 4328 inVal: addr(uint32(0)), 4329 want: addr(uint32(4294967295)), 4330 }, { 4331 name: name("Uints/Uint32/MaxOverflow"), 4332 inBuf: `4294967296`, 4333 inVal: addr(uint32(1)), 4334 want: addr(uint32(1)), 4335 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: uint32Type, Err: fmt.Errorf(`cannot parse "4294967296" as unsigned integer: %w`, strconv.ErrRange)}, 4336 }, { 4337 name: name("Uints/Uint64/Min"), 4338 inBuf: `0`, 4339 inVal: addr(uint64(1)), 4340 want: addr(uint64(0)), 4341 }, { 4342 name: name("Uints/Uint64/Max"), 4343 inBuf: `18446744073709551615`, 4344 inVal: addr(uint64(0)), 4345 want: addr(uint64(18446744073709551615)), 4346 }, { 4347 name: name("Uints/Uint64/MaxOverflow"), 4348 inBuf: `18446744073709551616`, 4349 inVal: addr(uint64(1)), 4350 want: addr(uint64(1)), 4351 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: uint64Type, Err: fmt.Errorf(`cannot parse "18446744073709551616" as unsigned integer: %w`, strconv.ErrRange)}, 4352 }, { 4353 name: name("Uints/Named"), 4354 inBuf: `6464`, 4355 inVal: addr(namedUint64(0)), 4356 want: addr(namedUint64(6464)), 4357 }, { 4358 name: name("Uints/Stringified"), 4359 uopts: UnmarshalOptions{StringifyNumbers: true}, 4360 inBuf: `"6464"`, 4361 inVal: new(uint), 4362 want: addr(uint(6464)), 4363 }, { 4364 name: name("Uints/Escaped"), 4365 uopts: UnmarshalOptions{StringifyNumbers: true}, 4366 inBuf: `"\u0036\u0034\u0036\u0034"`, 4367 inVal: new(uint), 4368 want: addr(uint(6464)), 4369 }, { 4370 name: name("Uints/Invalid/NegativeOne"), 4371 inBuf: `-1`, 4372 inVal: addr(uint(1)), 4373 want: addr(uint(1)), 4374 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: uintType, Err: fmt.Errorf(`cannot parse "-1" as unsigned integer: %w`, strconv.ErrSyntax)}, 4375 }, { 4376 name: name("Uints/Invalid/NegativeZero"), 4377 inBuf: `-0`, 4378 inVal: addr(uint(1)), 4379 want: addr(uint(1)), 4380 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: uintType, Err: fmt.Errorf(`cannot parse "-0" as unsigned integer: %w`, strconv.ErrSyntax)}, 4381 }, { 4382 name: name("Uints/Invalid/Fraction"), 4383 inBuf: `1.0`, 4384 inVal: addr(uint(10)), 4385 want: addr(uint(10)), 4386 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: uintType, Err: fmt.Errorf(`cannot parse "1.0" as unsigned integer: %w`, strconv.ErrSyntax)}, 4387 }, { 4388 name: name("Uints/Invalid/Exponent"), 4389 inBuf: `1e0`, 4390 inVal: addr(uint(10)), 4391 want: addr(uint(10)), 4392 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: uintType, Err: fmt.Errorf(`cannot parse "1e0" as unsigned integer: %w`, strconv.ErrSyntax)}, 4393 }, { 4394 name: name("Uints/Invalid/StringifiedFraction"), 4395 uopts: UnmarshalOptions{StringifyNumbers: true}, 4396 inBuf: `"1.0"`, 4397 inVal: addr(uint(10)), 4398 want: addr(uint(10)), 4399 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: uintType, Err: fmt.Errorf(`cannot parse "1.0" as unsigned integer: %w`, strconv.ErrSyntax)}, 4400 }, { 4401 name: name("Uints/Invalid/StringifiedExponent"), 4402 uopts: UnmarshalOptions{StringifyNumbers: true}, 4403 inBuf: `"1e0"`, 4404 inVal: addr(uint(10)), 4405 want: addr(uint(10)), 4406 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: uintType, Err: fmt.Errorf(`cannot parse "1e0" as unsigned integer: %w`, strconv.ErrSyntax)}, 4407 }, { 4408 name: name("Uints/Invalid/Overflow"), 4409 inBuf: `100000000000000000000000000000`, 4410 inVal: addr(uint(1)), 4411 want: addr(uint(1)), 4412 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: uintType, Err: fmt.Errorf(`cannot parse "100000000000000000000000000000" as unsigned integer: %w`, strconv.ErrRange)}, 4413 }, { 4414 name: name("Uints/Invalid/OverflowSyntax"), 4415 uopts: UnmarshalOptions{StringifyNumbers: true}, 4416 inBuf: `"100000000000000000000000000000x"`, 4417 inVal: addr(uint(1)), 4418 want: addr(uint(1)), 4419 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: uintType, Err: fmt.Errorf(`cannot parse "100000000000000000000000000000x" as unsigned integer: %w`, strconv.ErrSyntax)}, 4420 }, { 4421 name: name("Uints/Invalid/Whitespace"), 4422 uopts: UnmarshalOptions{StringifyNumbers: true}, 4423 inBuf: `"0 "`, 4424 inVal: addr(uint(1)), 4425 want: addr(uint(1)), 4426 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: uintType, Err: fmt.Errorf(`cannot parse "0 " as unsigned integer: %w`, strconv.ErrSyntax)}, 4427 }, { 4428 name: name("Uints/Invalid/Bool"), 4429 inBuf: `true`, 4430 inVal: addr(uint(1)), 4431 want: addr(uint(1)), 4432 wantErr: &SemanticError{action: "unmarshal", JSONKind: 't', GoType: uintType}, 4433 }, { 4434 name: name("Uints/Invalid/String"), 4435 inBuf: `"0"`, 4436 inVal: addr(uint(1)), 4437 want: addr(uint(1)), 4438 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: uintType}, 4439 }, { 4440 name: name("Uints/Invalid/Object"), 4441 inBuf: `{}`, 4442 inVal: addr(uint(1)), 4443 want: addr(uint(1)), 4444 wantErr: &SemanticError{action: "unmarshal", JSONKind: '{', GoType: uintType}, 4445 }, { 4446 name: name("Uints/Invalid/Array"), 4447 inBuf: `[]`, 4448 inVal: addr(uint(1)), 4449 want: addr(uint(1)), 4450 wantErr: &SemanticError{action: "unmarshal", JSONKind: '[', GoType: uintType}, 4451 }, { 4452 name: name("Uints/IgnoreInvalidFormat"), 4453 uopts: UnmarshalOptions{formatDepth: 1000, format: "invalid"}, 4454 inBuf: `1`, 4455 inVal: addr(uint(0)), 4456 want: addr(uint(1)), 4457 }, { 4458 name: name("Floats/Null"), 4459 inBuf: `null`, 4460 inVal: addr(float64(64.64)), 4461 want: addr(float64(0)), 4462 }, { 4463 name: name("Floats/Float32/Pi"), 4464 inBuf: `3.14159265358979323846264338327950288419716939937510582097494459`, 4465 inVal: addr(float32(32.32)), 4466 want: addr(float32(math.Pi)), 4467 }, { 4468 name: name("Floats/Float32/Underflow"), 4469 inBuf: `-1e1000`, 4470 inVal: addr(float32(32.32)), 4471 want: addr(float32(-math.MaxFloat32)), 4472 }, { 4473 name: name("Floats/Float32/Overflow"), 4474 inBuf: `-1e1000`, 4475 inVal: addr(float32(32.32)), 4476 want: addr(float32(-math.MaxFloat32)), 4477 }, { 4478 name: name("Floats/Float64/Pi"), 4479 inBuf: `3.14159265358979323846264338327950288419716939937510582097494459`, 4480 inVal: addr(float64(64.64)), 4481 want: addr(float64(math.Pi)), 4482 }, { 4483 name: name("Floats/Float64/Underflow"), 4484 inBuf: `-1e1000`, 4485 inVal: addr(float64(64.64)), 4486 want: addr(float64(-math.MaxFloat64)), 4487 }, { 4488 name: name("Floats/Float64/Overflow"), 4489 inBuf: `-1e1000`, 4490 inVal: addr(float64(64.64)), 4491 want: addr(float64(-math.MaxFloat64)), 4492 }, { 4493 name: name("Floats/Named"), 4494 inBuf: `64.64`, 4495 inVal: addr(namedFloat64(0)), 4496 want: addr(namedFloat64(64.64)), 4497 }, { 4498 name: name("Floats/Stringified"), 4499 uopts: UnmarshalOptions{StringifyNumbers: true}, 4500 inBuf: `"64.64"`, 4501 inVal: new(float64), 4502 want: addr(float64(64.64)), 4503 }, { 4504 name: name("Floats/Escaped"), 4505 uopts: UnmarshalOptions{StringifyNumbers: true}, 4506 inBuf: `"\u0036\u0034\u002e\u0036\u0034"`, 4507 inVal: new(float64), 4508 want: addr(float64(64.64)), 4509 }, { 4510 name: name("Floats/Invalid/NaN"), 4511 uopts: UnmarshalOptions{StringifyNumbers: true}, 4512 inBuf: `"NaN"`, 4513 inVal: addr(float64(64.64)), 4514 want: addr(float64(64.64)), 4515 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: float64Type, Err: fmt.Errorf(`cannot parse "NaN" as JSON number: %w`, strconv.ErrSyntax)}, 4516 }, { 4517 name: name("Floats/Invalid/Infinity"), 4518 uopts: UnmarshalOptions{StringifyNumbers: true}, 4519 inBuf: `"Infinity"`, 4520 inVal: addr(float64(64.64)), 4521 want: addr(float64(64.64)), 4522 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: float64Type, Err: fmt.Errorf(`cannot parse "Infinity" as JSON number: %w`, strconv.ErrSyntax)}, 4523 }, { 4524 name: name("Floats/Invalid/Whitespace"), 4525 uopts: UnmarshalOptions{StringifyNumbers: true}, 4526 inBuf: `"1 "`, 4527 inVal: addr(float64(64.64)), 4528 want: addr(float64(64.64)), 4529 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: float64Type, Err: fmt.Errorf(`cannot parse "1 " as JSON number: %w`, strconv.ErrSyntax)}, 4530 }, { 4531 name: name("Floats/Invalid/GoSyntax"), 4532 uopts: UnmarshalOptions{StringifyNumbers: true}, 4533 inBuf: `"1p-2"`, 4534 inVal: addr(float64(64.64)), 4535 want: addr(float64(64.64)), 4536 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: float64Type, Err: fmt.Errorf(`cannot parse "1p-2" as JSON number: %w`, strconv.ErrSyntax)}, 4537 }, { 4538 name: name("Floats/Invalid/Bool"), 4539 inBuf: `true`, 4540 inVal: addr(float64(64.64)), 4541 want: addr(float64(64.64)), 4542 wantErr: &SemanticError{action: "unmarshal", JSONKind: 't', GoType: float64Type}, 4543 }, { 4544 name: name("Floats/Invalid/String"), 4545 inBuf: `"0"`, 4546 inVal: addr(float64(64.64)), 4547 want: addr(float64(64.64)), 4548 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: float64Type}, 4549 }, { 4550 name: name("Floats/Invalid/Object"), 4551 inBuf: `{}`, 4552 inVal: addr(float64(64.64)), 4553 want: addr(float64(64.64)), 4554 wantErr: &SemanticError{action: "unmarshal", JSONKind: '{', GoType: float64Type}, 4555 }, { 4556 name: name("Floats/Invalid/Array"), 4557 inBuf: `[]`, 4558 inVal: addr(float64(64.64)), 4559 want: addr(float64(64.64)), 4560 wantErr: &SemanticError{action: "unmarshal", JSONKind: '[', GoType: float64Type}, 4561 }, { 4562 name: name("Floats/IgnoreInvalidFormat"), 4563 uopts: UnmarshalOptions{formatDepth: 1000, format: "invalid"}, 4564 inBuf: `1`, 4565 inVal: addr(float64(0)), 4566 want: addr(float64(1)), 4567 }, { 4568 name: name("Maps/Null"), 4569 inBuf: `null`, 4570 inVal: addr(map[string]string{"key": "value"}), 4571 want: new(map[string]string), 4572 }, { 4573 name: name("Maps/InvalidKey/Bool"), 4574 inBuf: `{"true":"false"}`, 4575 inVal: new(map[bool]bool), 4576 want: addr(make(map[bool]bool)), 4577 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: boolType}, 4578 }, { 4579 name: name("Maps/InvalidKey/NamedBool"), 4580 inBuf: `{"true":"false"}`, 4581 inVal: new(map[namedBool]bool), 4582 want: addr(make(map[namedBool]bool)), 4583 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: namedBoolType}, 4584 }, { 4585 name: name("Maps/InvalidKey/Array"), 4586 inBuf: `{"key":"value"}`, 4587 inVal: new(map[[1]string]string), 4588 want: addr(make(map[[1]string]string)), 4589 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array1StringType}, 4590 }, { 4591 name: name("Maps/InvalidKey/Channel"), 4592 inBuf: `{"key":"value"}`, 4593 inVal: new(map[chan string]string), 4594 want: addr(make(map[chan string]string)), 4595 wantErr: &SemanticError{action: "unmarshal", GoType: chanStringType}, 4596 }, { 4597 name: name("Maps/ValidKey/Int"), 4598 inBuf: `{"0":0,"-1":1,"2":2,"-3":3}`, 4599 inVal: new(map[int]int), 4600 want: addr(map[int]int{0: 0, -1: 1, 2: 2, -3: 3}), 4601 }, { 4602 name: name("Maps/ValidKey/NamedInt"), 4603 inBuf: `{"0":0,"-1":1,"2":2,"-3":3}`, 4604 inVal: new(map[namedInt64]int), 4605 want: addr(map[namedInt64]int{0: 0, -1: 1, 2: 2, -3: 3}), 4606 }, { 4607 name: name("Maps/ValidKey/Uint"), 4608 inBuf: `{"0":0,"1":1,"2":2,"3":3}`, 4609 inVal: new(map[uint]uint), 4610 want: addr(map[uint]uint{0: 0, 1: 1, 2: 2, 3: 3}), 4611 }, { 4612 name: name("Maps/ValidKey/NamedUint"), 4613 inBuf: `{"0":0,"1":1,"2":2,"3":3}`, 4614 inVal: new(map[namedUint64]uint), 4615 want: addr(map[namedUint64]uint{0: 0, 1: 1, 2: 2, 3: 3}), 4616 }, { 4617 name: name("Maps/ValidKey/Float"), 4618 inBuf: `{"1.234":1.234,"12.34":12.34,"123.4":123.4}`, 4619 inVal: new(map[float64]float64), 4620 want: addr(map[float64]float64{1.234: 1.234, 12.34: 12.34, 123.4: 123.4}), 4621 }, { 4622 name: name("Maps/DuplicateName/Int"), 4623 inBuf: `{"0":1,"-0":-1}`, 4624 inVal: new(map[int]int), 4625 want: addr(map[int]int{0: 1}), 4626 wantErr: (&SyntacticError{str: `duplicate name "-0" in object`}).withOffset(int64(len(`{"0":1,`))), 4627 }, { 4628 name: name("Maps/DuplicateName/Int/AllowDuplicateNames"), 4629 dopts: DecodeOptions{AllowDuplicateNames: true}, 4630 inBuf: `{"0":1,"-0":-1}`, 4631 inVal: new(map[int]int), 4632 want: addr(map[int]int{0: -1}), // latter takes precedence 4633 }, { 4634 name: name("Maps/DuplicateName/Int/OverwriteExisting"), 4635 inBuf: `{"-0":-1}`, 4636 inVal: addr(map[int]int{0: 1}), 4637 want: addr(map[int]int{0: -1}), 4638 }, { 4639 name: name("Maps/DuplicateName/Float"), 4640 inBuf: `{"1.0":"1.0","1":"1","1e0":"1e0"}`, 4641 inVal: new(map[float64]string), 4642 want: addr(map[float64]string{1: "1.0"}), 4643 wantErr: (&SyntacticError{str: `duplicate name "1" in object`}).withOffset(int64(len(`{"1.0":"1.0",`))), 4644 }, { 4645 name: name("Maps/DuplicateName/Float/AllowDuplicateNames"), 4646 dopts: DecodeOptions{AllowDuplicateNames: true}, 4647 inBuf: `{"1.0":"1.0","1":"1","1e0":"1e0"}`, 4648 inVal: new(map[float64]string), 4649 want: addr(map[float64]string{1: "1e0"}), // latter takes precedence 4650 }, { 4651 name: name("Maps/DuplicateName/Float/OverwriteExisting"), 4652 inBuf: `{"1.0":"1.0"}`, 4653 inVal: addr(map[float64]string{1: "1"}), 4654 want: addr(map[float64]string{1: "1.0"}), 4655 }, { 4656 name: name("Maps/DuplicateName/NoCaseString"), 4657 inBuf: `{"hello":"hello","HELLO":"HELLO"}`, 4658 inVal: new(map[nocaseString]string), 4659 want: addr(map[nocaseString]string{"hello": "hello"}), 4660 wantErr: (&SyntacticError{str: `duplicate name "HELLO" in object`}).withOffset(int64(len(`{"hello":"hello",`))), 4661 }, { 4662 name: name("Maps/DuplicateName/NoCaseString/AllowDuplicateNames"), 4663 dopts: DecodeOptions{AllowDuplicateNames: true}, 4664 inBuf: `{"hello":"hello","HELLO":"HELLO"}`, 4665 inVal: new(map[nocaseString]string), 4666 want: addr(map[nocaseString]string{"hello": "HELLO"}), // latter takes precedence 4667 }, { 4668 name: name("Maps/DuplicateName/NoCaseString/OverwriteExisting"), 4669 dopts: DecodeOptions{AllowDuplicateNames: true}, 4670 inBuf: `{"HELLO":"HELLO"}`, 4671 inVal: addr(map[nocaseString]string{"hello": "hello"}), 4672 want: addr(map[nocaseString]string{"hello": "HELLO"}), 4673 }, { 4674 name: name("Maps/ValidKey/Interface"), 4675 inBuf: `{"false":"false","true":"true","string":"string","0":"0","[]":"[]","{}":"{}"}`, 4676 inVal: new(map[any]string), 4677 want: addr(map[any]string{ 4678 "false": "false", 4679 "true": "true", 4680 "string": "string", 4681 "0": "0", 4682 "[]": "[]", 4683 "{}": "{}", 4684 }), 4685 }, { 4686 name: name("Maps/InvalidValue/Channel"), 4687 inBuf: `{"key":"value"}`, 4688 inVal: new(map[string]chan string), 4689 want: addr(map[string]chan string{ 4690 "key": nil, 4691 }), 4692 wantErr: &SemanticError{action: "unmarshal", GoType: chanStringType}, 4693 }, { 4694 name: name("Maps/RecursiveMap"), 4695 inBuf: `{"buzz":{},"fizz":{"bar":{},"foo":{}}}`, 4696 inVal: new(recursiveMap), 4697 want: addr(recursiveMap{ 4698 "fizz": { 4699 "foo": {}, 4700 "bar": {}, 4701 }, 4702 "buzz": {}, 4703 }), 4704 }, { 4705 // NOTE: The semantics differs from v1, 4706 // where existing map entries were not merged into. 4707 // See https://go.dev/issue/31924. 4708 name: name("Maps/Merge"), 4709 dopts: DecodeOptions{AllowDuplicateNames: true}, 4710 inBuf: `{"k1":{"k2":"v2"},"k2":{"k1":"v1"},"k2":{"k2":"v2"}}`, 4711 inVal: addr(map[string]map[string]string{ 4712 "k1": {"k1": "v1"}, 4713 }), 4714 want: addr(map[string]map[string]string{ 4715 "k1": {"k1": "v1", "k2": "v2"}, 4716 "k2": {"k1": "v1", "k2": "v2"}, 4717 }), 4718 }, { 4719 name: name("Maps/Invalid/Bool"), 4720 inBuf: `true`, 4721 inVal: addr(map[string]string{"key": "value"}), 4722 want: addr(map[string]string{"key": "value"}), 4723 wantErr: &SemanticError{action: "unmarshal", JSONKind: 't', GoType: mapStringStringType}, 4724 }, { 4725 name: name("Maps/Invalid/String"), 4726 inBuf: `""`, 4727 inVal: addr(map[string]string{"key": "value"}), 4728 want: addr(map[string]string{"key": "value"}), 4729 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: mapStringStringType}, 4730 }, { 4731 name: name("Maps/Invalid/Number"), 4732 inBuf: `0`, 4733 inVal: addr(map[string]string{"key": "value"}), 4734 want: addr(map[string]string{"key": "value"}), 4735 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: mapStringStringType}, 4736 }, { 4737 name: name("Maps/Invalid/Array"), 4738 inBuf: `[]`, 4739 inVal: addr(map[string]string{"key": "value"}), 4740 want: addr(map[string]string{"key": "value"}), 4741 wantErr: &SemanticError{action: "unmarshal", JSONKind: '[', GoType: mapStringStringType}, 4742 }, { 4743 name: name("Maps/IgnoreInvalidFormat"), 4744 uopts: UnmarshalOptions{formatDepth: 1000, format: "invalid"}, 4745 inBuf: `{"hello":"goodbye"}`, 4746 inVal: addr(map[string]string{}), 4747 want: addr(map[string]string{"hello": "goodbye"}), 4748 }, { 4749 name: name("Structs/Null"), 4750 inBuf: `null`, 4751 inVal: addr(structAll{String: "something"}), 4752 want: addr(structAll{}), 4753 }, { 4754 name: name("Structs/Empty"), 4755 inBuf: `{}`, 4756 inVal: addr(structAll{ 4757 String: "hello", 4758 Map: map[string]string{}, 4759 Slice: []string{}, 4760 }), 4761 want: addr(structAll{ 4762 String: "hello", 4763 Map: map[string]string{}, 4764 Slice: []string{}, 4765 }), 4766 }, { 4767 name: name("Structs/Normal"), 4768 inBuf: `{ 4769 "Bool": true, 4770 "String": "hello", 4771 "Bytes": "AQID", 4772 "Int": -64, 4773 "Uint": 64, 4774 "Float": 3.14159, 4775 "Map": {"key": "value"}, 4776 "StructScalars": { 4777 "Bool": true, 4778 "String": "hello", 4779 "Bytes": "AQID", 4780 "Int": -64, 4781 "Uint": 64, 4782 "Float": 3.14159 4783 }, 4784 "StructMaps": { 4785 "MapBool": {"": true}, 4786 "MapString": {"": "hello"}, 4787 "MapBytes": {"": "AQID"}, 4788 "MapInt": {"": -64}, 4789 "MapUint": {"": 64}, 4790 "MapFloat": {"": 3.14159} 4791 }, 4792 "StructSlices": { 4793 "SliceBool": [true], 4794 "SliceString": ["hello"], 4795 "SliceBytes": ["AQID"], 4796 "SliceInt": [-64], 4797 "SliceUint": [64], 4798 "SliceFloat": [3.14159] 4799 }, 4800 "Slice": ["fizz","buzz"], 4801 "Array": ["goodbye"], 4802 "Pointer": {}, 4803 "Interface": null 4804 }`, 4805 inVal: new(structAll), 4806 want: addr(structAll{ 4807 Bool: true, 4808 String: "hello", 4809 Bytes: []byte{1, 2, 3}, 4810 Int: -64, 4811 Uint: +64, 4812 Float: 3.14159, 4813 Map: map[string]string{"key": "value"}, 4814 StructScalars: structScalars{ 4815 Bool: true, 4816 String: "hello", 4817 Bytes: []byte{1, 2, 3}, 4818 Int: -64, 4819 Uint: +64, 4820 Float: 3.14159, 4821 }, 4822 StructMaps: structMaps{ 4823 MapBool: map[string]bool{"": true}, 4824 MapString: map[string]string{"": "hello"}, 4825 MapBytes: map[string][]byte{"": {1, 2, 3}}, 4826 MapInt: map[string]int64{"": -64}, 4827 MapUint: map[string]uint64{"": +64}, 4828 MapFloat: map[string]float64{"": 3.14159}, 4829 }, 4830 StructSlices: structSlices{ 4831 SliceBool: []bool{true}, 4832 SliceString: []string{"hello"}, 4833 SliceBytes: [][]byte{{1, 2, 3}}, 4834 SliceInt: []int64{-64}, 4835 SliceUint: []uint64{+64}, 4836 SliceFloat: []float64{3.14159}, 4837 }, 4838 Slice: []string{"fizz", "buzz"}, 4839 Array: [1]string{"goodbye"}, 4840 Pointer: new(structAll), 4841 }), 4842 }, { 4843 name: name("Structs/Merge"), 4844 inBuf: `{ 4845 "Bool": false, 4846 "String": "goodbye", 4847 "Int": -64, 4848 "Float": 3.14159, 4849 "Map": {"k2": "v2"}, 4850 "StructScalars": { 4851 "Bool": true, 4852 "String": "hello", 4853 "Bytes": "AQID", 4854 "Int": -64 4855 }, 4856 "StructMaps": { 4857 "MapBool": {"": true}, 4858 "MapString": {"": "hello"}, 4859 "MapBytes": {"": "AQID"}, 4860 "MapInt": {"": -64}, 4861 "MapUint": {"": 64}, 4862 "MapFloat": {"": 3.14159} 4863 }, 4864 "StructSlices": { 4865 "SliceString": ["hello"], 4866 "SliceBytes": ["AQID"], 4867 "SliceInt": [-64], 4868 "SliceUint": [64] 4869 }, 4870 "Slice": ["fizz","buzz"], 4871 "Array": ["goodbye"], 4872 "Pointer": {}, 4873 "Interface": {"k2":"v2"} 4874 }`, 4875 inVal: addr(structAll{ 4876 Bool: true, 4877 String: "hello", 4878 Bytes: []byte{1, 2, 3}, 4879 Uint: +64, 4880 Float: math.NaN(), 4881 Map: map[string]string{"k1": "v1"}, 4882 StructScalars: structScalars{ 4883 String: "hello", 4884 Bytes: make([]byte, 2, 4), 4885 Uint: +64, 4886 Float: 3.14159, 4887 }, 4888 StructMaps: structMaps{ 4889 MapBool: map[string]bool{"": false}, 4890 MapBytes: map[string][]byte{"": {}}, 4891 MapInt: map[string]int64{"": 123}, 4892 MapFloat: map[string]float64{"": math.Inf(+1)}, 4893 }, 4894 StructSlices: structSlices{ 4895 SliceBool: []bool{true}, 4896 SliceBytes: [][]byte{nil, nil}, 4897 SliceInt: []int64{-123}, 4898 SliceUint: []uint64{+123}, 4899 SliceFloat: []float64{3.14159}, 4900 }, 4901 Slice: []string{"buzz", "fizz", "gizz"}, 4902 Array: [1]string{"hello"}, 4903 Pointer: new(structAll), 4904 Interface: map[string]string{"k1": "v1"}, 4905 }), 4906 want: addr(structAll{ 4907 Bool: false, 4908 String: "goodbye", 4909 Bytes: []byte{1, 2, 3}, 4910 Int: -64, 4911 Uint: +64, 4912 Float: 3.14159, 4913 Map: map[string]string{"k1": "v1", "k2": "v2"}, 4914 StructScalars: structScalars{ 4915 Bool: true, 4916 String: "hello", 4917 Bytes: []byte{1, 2, 3}, 4918 Int: -64, 4919 Uint: +64, 4920 Float: 3.14159, 4921 }, 4922 StructMaps: structMaps{ 4923 MapBool: map[string]bool{"": true}, 4924 MapString: map[string]string{"": "hello"}, 4925 MapBytes: map[string][]byte{"": {1, 2, 3}}, 4926 MapInt: map[string]int64{"": -64}, 4927 MapUint: map[string]uint64{"": +64}, 4928 MapFloat: map[string]float64{"": 3.14159}, 4929 }, 4930 StructSlices: structSlices{ 4931 SliceBool: []bool{true}, 4932 SliceString: []string{"hello"}, 4933 SliceBytes: [][]byte{{1, 2, 3}}, 4934 SliceInt: []int64{-64}, 4935 SliceUint: []uint64{+64}, 4936 SliceFloat: []float64{3.14159}, 4937 }, 4938 Slice: []string{"fizz", "buzz"}, 4939 Array: [1]string{"goodbye"}, 4940 Pointer: new(structAll), 4941 Interface: map[string]string{"k1": "v1", "k2": "v2"}, 4942 }), 4943 }, { 4944 name: name("Structs/Stringified/Normal"), 4945 inBuf: `{ 4946 "Bool": true, 4947 "String": "hello", 4948 "Bytes": "AQID", 4949 "Int": -64, 4950 "Uint": 64, 4951 "Float": 3.14159, 4952 "Map": {"key": "value"}, 4953 "StructScalars": { 4954 "Bool": true, 4955 "String": "hello", 4956 "Bytes": "AQID", 4957 "Int": -64, 4958 "Uint": 64, 4959 "Float": 3.14159 4960 }, 4961 "StructMaps": { 4962 "MapBool": {"": true}, 4963 "MapString": {"": "hello"}, 4964 "MapBytes": {"": "AQID"}, 4965 "MapInt": {"": -64}, 4966 "MapUint": {"": 64}, 4967 "MapFloat": {"": 3.14159} 4968 }, 4969 "StructSlices": { 4970 "SliceBool": [true], 4971 "SliceString": ["hello"], 4972 "SliceBytes": ["AQID"], 4973 "SliceInt": [-64], 4974 "SliceUint": [64], 4975 "SliceFloat": [3.14159] 4976 }, 4977 "Slice": ["fizz","buzz"], 4978 "Array": ["goodbye"], 4979 "Pointer": {}, 4980 "Interface": null 4981 }`, 4982 inVal: new(structStringifiedAll), 4983 want: addr(structStringifiedAll{ 4984 Bool: true, 4985 String: "hello", 4986 Bytes: []byte{1, 2, 3}, 4987 Int: -64, // may be stringified 4988 Uint: +64, // may be stringified 4989 Float: 3.14159, // may be stringified 4990 Map: map[string]string{"key": "value"}, 4991 StructScalars: structScalars{ 4992 Bool: true, 4993 String: "hello", 4994 Bytes: []byte{1, 2, 3}, 4995 Int: -64, // may be stringified 4996 Uint: +64, // may be stringified 4997 Float: 3.14159, // may be stringified 4998 }, 4999 StructMaps: structMaps{ 5000 MapBool: map[string]bool{"": true}, 5001 MapString: map[string]string{"": "hello"}, 5002 MapBytes: map[string][]byte{"": {1, 2, 3}}, 5003 MapInt: map[string]int64{"": -64}, // may be stringified 5004 MapUint: map[string]uint64{"": +64}, // may be stringified 5005 MapFloat: map[string]float64{"": 3.14159}, // may be stringified 5006 }, 5007 StructSlices: structSlices{ 5008 SliceBool: []bool{true}, 5009 SliceString: []string{"hello"}, 5010 SliceBytes: [][]byte{{1, 2, 3}}, 5011 SliceInt: []int64{-64}, // may be stringified 5012 SliceUint: []uint64{+64}, // may be stringified 5013 SliceFloat: []float64{3.14159}, // may be stringified 5014 }, 5015 Slice: []string{"fizz", "buzz"}, 5016 Array: [1]string{"goodbye"}, 5017 Pointer: new(structStringifiedAll), // may be stringified 5018 }), 5019 }, { 5020 name: name("Structs/Stringified/String"), 5021 inBuf: `{ 5022 "Bool": true, 5023 "String": "hello", 5024 "Bytes": "AQID", 5025 "Int": "-64", 5026 "Uint": "64", 5027 "Float": "3.14159", 5028 "Map": {"key": "value"}, 5029 "StructScalars": { 5030 "Bool": true, 5031 "String": "hello", 5032 "Bytes": "AQID", 5033 "Int": "-64", 5034 "Uint": "64", 5035 "Float": "3.14159" 5036 }, 5037 "StructMaps": { 5038 "MapBool": {"": true}, 5039 "MapString": {"": "hello"}, 5040 "MapBytes": {"": "AQID"}, 5041 "MapInt": {"": "-64"}, 5042 "MapUint": {"": "64"}, 5043 "MapFloat": {"": "3.14159"} 5044 }, 5045 "StructSlices": { 5046 "SliceBool": [true], 5047 "SliceString": ["hello"], 5048 "SliceBytes": ["AQID"], 5049 "SliceInt": ["-64"], 5050 "SliceUint": ["64"], 5051 "SliceFloat": ["3.14159"] 5052 }, 5053 "Slice": ["fizz","buzz"], 5054 "Array": ["goodbye"], 5055 "Pointer": {}, 5056 "Interface": null 5057 }`, 5058 inVal: new(structStringifiedAll), 5059 want: addr(structStringifiedAll{ 5060 Bool: true, 5061 String: "hello", 5062 Bytes: []byte{1, 2, 3}, 5063 Int: -64, // may be stringified 5064 Uint: +64, // may be stringified 5065 Float: 3.14159, // may be stringified 5066 Map: map[string]string{"key": "value"}, 5067 StructScalars: structScalars{ 5068 Bool: true, 5069 String: "hello", 5070 Bytes: []byte{1, 2, 3}, 5071 Int: -64, // may be stringified 5072 Uint: +64, // may be stringified 5073 Float: 3.14159, // may be stringified 5074 }, 5075 StructMaps: structMaps{ 5076 MapBool: map[string]bool{"": true}, 5077 MapString: map[string]string{"": "hello"}, 5078 MapBytes: map[string][]byte{"": {1, 2, 3}}, 5079 MapInt: map[string]int64{"": -64}, // may be stringified 5080 MapUint: map[string]uint64{"": +64}, // may be stringified 5081 MapFloat: map[string]float64{"": 3.14159}, // may be stringified 5082 }, 5083 StructSlices: structSlices{ 5084 SliceBool: []bool{true}, 5085 SliceString: []string{"hello"}, 5086 SliceBytes: [][]byte{{1, 2, 3}}, 5087 SliceInt: []int64{-64}, // may be stringified 5088 SliceUint: []uint64{+64}, // may be stringified 5089 SliceFloat: []float64{3.14159}, // may be stringified 5090 }, 5091 Slice: []string{"fizz", "buzz"}, 5092 Array: [1]string{"goodbye"}, 5093 Pointer: new(structStringifiedAll), // may be stringified 5094 }), 5095 }, { 5096 name: name("Structs/Format/Bytes"), 5097 inBuf: `{ 5098 "Base16": "0123456789abcdef", 5099 "Base32": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", 5100 "Base32Hex": "0123456789ABCDEFGHIJKLMNOPQRSTUV", 5101 "Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", 5102 "Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", 5103 "Array": [1, 2, 3, 4] 5104 }`, 5105 inVal: new(structFormatBytes), 5106 want: addr(structFormatBytes{ 5107 Base16: []byte("\x01\x23\x45\x67\x89\xab\xcd\xef"), 5108 Base32: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"), 5109 Base32Hex: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"), 5110 Base64: []byte("\x00\x10\x83\x10Q\x87 \x92\x8b0ӏA\x14\x93QU\x97a\x96\x9bqן\x82\x18\xa3\x92Y\xa7\xa2\x9a\xab\xb2ۯ\xc3\x1c\xb3\xd3]\xb7㞻\xf3߿"), 5111 Base64URL: []byte("\x00\x10\x83\x10Q\x87 \x92\x8b0ӏA\x14\x93QU\x97a\x96\x9bqן\x82\x18\xa3\x92Y\xa7\xa2\x9a\xab\xb2ۯ\xc3\x1c\xb3\xd3]\xb7㞻\xf3߿"), 5112 Array: []byte{1, 2, 3, 4}, 5113 }), 5114 }, { 5115 name: name("Structs/Format/Bytes/Array"), 5116 uopts: UnmarshalOptions{Unmarshalers: UnmarshalFuncV1(func(b []byte, v *byte) error { 5117 if string(b) == "true" { 5118 *v = 1 5119 } else { 5120 *v = 0 5121 } 5122 return nil 5123 })}, 5124 inBuf: `{"Array":[false,true,false,true,false,true]}`, 5125 inVal: new(struct { 5126 Array []byte `json:",format:array"` 5127 }), 5128 want: addr(struct { 5129 Array []byte `json:",format:array"` 5130 }{ 5131 Array: []byte{0, 1, 0, 1, 0, 1}, 5132 }), 5133 }, { 5134 name: name("Structs/Format/Bytes/Invalid/Base16/WrongKind"), 5135 inBuf: `{"Base16": [1,2,3,4]}`, 5136 inVal: new(structFormatBytes), 5137 wantErr: &SemanticError{action: "unmarshal", JSONKind: '[', GoType: bytesType}, 5138 }, { 5139 name: name("Structs/Format/Bytes/Invalid/Base16/AllPadding"), 5140 inBuf: `{"Base16": "===="}`, 5141 inVal: new(structFormatBytes), 5142 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: func() error { 5143 _, err := hex.Decode(make([]byte, 2), []byte("=====")) 5144 return err 5145 }()}, 5146 }, { 5147 name: name("Structs/Format/Bytes/Invalid/Base16/EvenPadding"), 5148 inBuf: `{"Base16": "0123456789abcdef="}`, 5149 inVal: new(structFormatBytes), 5150 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: func() error { 5151 _, err := hex.Decode(make([]byte, 8), []byte("0123456789abcdef=")) 5152 return err 5153 }()}, 5154 }, { 5155 name: name("Structs/Format/Bytes/Invalid/Base16/OddPadding"), 5156 inBuf: `{"Base16": "0123456789abcdef0="}`, 5157 inVal: new(structFormatBytes), 5158 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: func() error { 5159 _, err := hex.Decode(make([]byte, 9), []byte("0123456789abcdef0=")) 5160 return err 5161 }()}, 5162 }, { 5163 name: name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/LineFeed"), 5164 inBuf: `{"Base16": "aa\naa"}`, 5165 inVal: new(structFormatBytes), 5166 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: func() error { 5167 _, err := hex.Decode(make([]byte, 9), []byte("aa\naa")) 5168 return err 5169 }()}, 5170 }, { 5171 name: name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/CarriageReturn"), 5172 inBuf: `{"Base16": "aa\raa"}`, 5173 inVal: new(structFormatBytes), 5174 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: func() error { 5175 _, err := hex.Decode(make([]byte, 9), []byte("aa\raa")) 5176 return err 5177 }()}, 5178 }, { 5179 name: name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/Space"), 5180 inBuf: `{"Base16": "aa aa"}`, 5181 inVal: new(structFormatBytes), 5182 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: func() error { 5183 _, err := hex.Decode(make([]byte, 9), []byte("aa aa")) 5184 return err 5185 }()}, 5186 }, { 5187 name: name("Structs/Format/Bytes/Invalid/Base32/Padding"), 5188 inBuf: `[ 5189 {"Base32": "NA======"}, 5190 {"Base32": "NBSQ===="}, 5191 {"Base32": "NBSWY==="}, 5192 {"Base32": "NBSWY3A="}, 5193 {"Base32": "NBSWY3DP"} 5194 ]`, 5195 inVal: new([]structFormatBytes), 5196 want: addr([]structFormatBytes{ 5197 {Base32: []byte("h")}, 5198 {Base32: []byte("he")}, 5199 {Base32: []byte("hel")}, 5200 {Base32: []byte("hell")}, 5201 {Base32: []byte("hello")}, 5202 }), 5203 }, { 5204 name: name("Structs/Format/Bytes/Invalid/Base32/Invalid/NoPadding"), 5205 inBuf: `[ 5206 {"Base32": "NA"}, 5207 {"Base32": "NBSQ"}, 5208 {"Base32": "NBSWY"}, 5209 {"Base32": "NBSWY3A"}, 5210 {"Base32": "NBSWY3DP"} 5211 ]`, 5212 inVal: new([]structFormatBytes), 5213 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: func() error { 5214 _, err := base32.StdEncoding.Decode(make([]byte, 1), []byte("NA")) 5215 return err 5216 }()}, 5217 }, { 5218 name: name("Structs/Format/Bytes/Invalid/Base32/WrongAlphabet"), 5219 inBuf: `{"Base32": "0123456789ABCDEFGHIJKLMNOPQRSTUV"}`, 5220 inVal: new(structFormatBytes), 5221 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: func() error { 5222 _, err := base32.StdEncoding.Decode(make([]byte, 20), []byte("0123456789ABCDEFGHIJKLMNOPQRSTUV")) 5223 return err 5224 }()}, 5225 }, { 5226 name: name("Structs/Format/Bytes/Invalid/Base32Hex/WrongAlphabet"), 5227 inBuf: `{"Base32Hex": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"}`, 5228 inVal: new(structFormatBytes), 5229 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: func() error { 5230 _, err := base32.HexEncoding.Decode(make([]byte, 20), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567")) 5231 return err 5232 }()}, 5233 }, { 5234 name: name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/LineFeed"), 5235 inBuf: `{"Base32": "AAAA\nAAAA"}`, 5236 inVal: new(structFormatBytes), 5237 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: errors.New("illegal data at input byte 4")}, 5238 }, { 5239 name: name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/CarriageReturn"), 5240 inBuf: `{"Base32": "AAAA\rAAAA"}`, 5241 inVal: new(structFormatBytes), 5242 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: errors.New("illegal data at input byte 4")}, 5243 }, { 5244 name: name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/Space"), 5245 inBuf: `{"Base32": "AAAA AAAA"}`, 5246 inVal: new(structFormatBytes), 5247 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: base32.CorruptInputError(4)}, 5248 }, { 5249 name: name("Structs/Format/Bytes/Invalid/Base64/WrongAlphabet"), 5250 inBuf: `{"Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"}`, 5251 inVal: new(structFormatBytes), 5252 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: func() error { 5253 _, err := base64.StdEncoding.Decode(make([]byte, 48), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_")) 5254 return err 5255 }()}, 5256 }, { 5257 name: name("Structs/Format/Bytes/Invalid/Base64URL/WrongAlphabet"), 5258 inBuf: `{"Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"}`, 5259 inVal: new(structFormatBytes), 5260 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: func() error { 5261 _, err := base64.URLEncoding.Decode(make([]byte, 48), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")) 5262 return err 5263 }()}, 5264 }, { 5265 name: name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/LineFeed"), 5266 inBuf: `{"Base64": "aa=\n="}`, 5267 inVal: new(structFormatBytes), 5268 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: errors.New("illegal data at input byte 3")}, 5269 }, { 5270 name: name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/CarriageReturn"), 5271 inBuf: `{"Base64": "aa=\r="}`, 5272 inVal: new(structFormatBytes), 5273 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: errors.New("illegal data at input byte 3")}, 5274 }, { 5275 name: name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/Space"), 5276 inBuf: `{"Base64": "aa= ="}`, 5277 inVal: new(structFormatBytes), 5278 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: bytesType, Err: base64.CorruptInputError(2)}, 5279 }, { 5280 name: name("Structs/Format/Floats"), 5281 inBuf: `[ 5282 {"NonFinite": 3.141592653589793, "PointerNonFinite": 3.141592653589793}, 5283 {"NonFinite": "-Infinity", "PointerNonFinite": "-Infinity"}, 5284 {"NonFinite": "Infinity", "PointerNonFinite": "Infinity"} 5285 ]`, 5286 inVal: new([]structFormatFloats), 5287 want: addr([]structFormatFloats{ 5288 {NonFinite: math.Pi, PointerNonFinite: addr(math.Pi)}, 5289 {NonFinite: math.Inf(-1), PointerNonFinite: addr(math.Inf(-1))}, 5290 {NonFinite: math.Inf(+1), PointerNonFinite: addr(math.Inf(+1))}, 5291 }), 5292 }, { 5293 name: name("Structs/Format/Floats/NaN"), 5294 inBuf: `{"NonFinite": "NaN"}`, 5295 inVal: new(structFormatFloats), 5296 // Avoid checking want since reflect.DeepEqual fails for NaNs. 5297 }, { 5298 name: name("Structs/Format/Floats/Invalid/NaN"), 5299 inBuf: `{"NonFinite": "nan"}`, 5300 inVal: new(structFormatFloats), 5301 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: float64Type}, 5302 }, { 5303 name: name("Structs/Format/Floats/Invalid/PositiveInfinity"), 5304 inBuf: `{"NonFinite": "+Infinity"}`, 5305 inVal: new(structFormatFloats), 5306 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: float64Type}, 5307 }, { 5308 name: name("Structs/Format/Floats/Invalid/NegativeInfinitySpace"), 5309 inBuf: `{"NonFinite": "-Infinity "}`, 5310 inVal: new(structFormatFloats), 5311 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: float64Type}, 5312 }, { 5313 name: name("Structs/Format/Maps"), 5314 inBuf: `[ 5315 {"EmitNull": null, "PointerEmitNull": null}, 5316 {"EmitNull": {}, "PointerEmitNull": {}}, 5317 {"EmitNull": {"k": "v"}, "PointerEmitNull": {"k": "v"}} 5318 ]`, 5319 inVal: new([]structFormatMaps), 5320 want: addr([]structFormatMaps{ 5321 {EmitNull: nil, PointerEmitNull: nil}, 5322 {EmitNull: map[string]string{}, PointerEmitNull: addr(map[string]string{})}, 5323 {EmitNull: map[string]string{"k": "v"}, PointerEmitNull: addr(map[string]string{"k": "v"})}, 5324 }), 5325 }, { 5326 name: name("Structs/Format/Slices"), 5327 inBuf: `[ 5328 {"EmitNull": null, "PointerEmitNull": null}, 5329 {"EmitNull": [], "PointerEmitNull": []}, 5330 {"EmitNull": ["v"], "PointerEmitNull": ["v"]} 5331 ]`, 5332 inVal: new([]structFormatSlices), 5333 want: addr([]structFormatSlices{ 5334 {EmitNull: nil, PointerEmitNull: nil}, 5335 {EmitNull: []string{}, PointerEmitNull: addr([]string{})}, 5336 {EmitNull: []string{"v"}, PointerEmitNull: addr([]string{"v"})}, 5337 }), 5338 }, { 5339 name: name("Structs/Format/Invalid/Bool"), 5340 inBuf: `{"Bool":true}`, 5341 inVal: new(structFormatInvalid), 5342 wantErr: &SemanticError{action: "unmarshal", GoType: boolType, Err: errors.New(`invalid format flag: "invalid"`)}, 5343 }, { 5344 name: name("Structs/Format/Invalid/String"), 5345 inBuf: `{"String": "string"}`, 5346 inVal: new(structFormatInvalid), 5347 wantErr: &SemanticError{action: "unmarshal", GoType: stringType, Err: errors.New(`invalid format flag: "invalid"`)}, 5348 }, { 5349 name: name("Structs/Format/Invalid/Bytes"), 5350 inBuf: `{"Bytes": "bytes"}`, 5351 inVal: new(structFormatInvalid), 5352 wantErr: &SemanticError{action: "unmarshal", GoType: bytesType, Err: errors.New(`invalid format flag: "invalid"`)}, 5353 }, { 5354 name: name("Structs/Format/Invalid/Int"), 5355 inBuf: `{"Int": 1}`, 5356 inVal: new(structFormatInvalid), 5357 wantErr: &SemanticError{action: "unmarshal", GoType: int64Type, Err: errors.New(`invalid format flag: "invalid"`)}, 5358 }, { 5359 name: name("Structs/Format/Invalid/Uint"), 5360 inBuf: `{"Uint": 1}`, 5361 inVal: new(structFormatInvalid), 5362 wantErr: &SemanticError{action: "unmarshal", GoType: uint64Type, Err: errors.New(`invalid format flag: "invalid"`)}, 5363 }, { 5364 name: name("Structs/Format/Invalid/Float"), 5365 inBuf: `{"Float": 1}`, 5366 inVal: new(structFormatInvalid), 5367 wantErr: &SemanticError{action: "unmarshal", GoType: float64Type, Err: errors.New(`invalid format flag: "invalid"`)}, 5368 }, { 5369 name: name("Structs/Format/Invalid/Map"), 5370 inBuf: `{"Map":{}}`, 5371 inVal: new(structFormatInvalid), 5372 wantErr: &SemanticError{action: "unmarshal", GoType: mapStringStringType, Err: errors.New(`invalid format flag: "invalid"`)}, 5373 }, { 5374 name: name("Structs/Format/Invalid/Struct"), 5375 inBuf: `{"Struct": {}}`, 5376 inVal: new(structFormatInvalid), 5377 wantErr: &SemanticError{action: "unmarshal", GoType: structAllType, Err: errors.New(`invalid format flag: "invalid"`)}, 5378 }, { 5379 name: name("Structs/Format/Invalid/Slice"), 5380 inBuf: `{"Slice": {}}`, 5381 inVal: new(structFormatInvalid), 5382 wantErr: &SemanticError{action: "unmarshal", GoType: sliceStringType, Err: errors.New(`invalid format flag: "invalid"`)}, 5383 }, { 5384 name: name("Structs/Format/Invalid/Array"), 5385 inBuf: `{"Array": []}`, 5386 inVal: new(structFormatInvalid), 5387 wantErr: &SemanticError{action: "unmarshal", GoType: array1StringType, Err: errors.New(`invalid format flag: "invalid"`)}, 5388 }, { 5389 name: name("Structs/Format/Invalid/Interface"), 5390 inBuf: `{"Interface": "anything"}`, 5391 inVal: new(structFormatInvalid), 5392 wantErr: &SemanticError{action: "unmarshal", GoType: anyType, Err: errors.New(`invalid format flag: "invalid"`)}, 5393 }, { 5394 name: name("Structs/Inline/Zero"), 5395 inBuf: `{"D":""}`, 5396 inVal: new(structInlined), 5397 want: new(structInlined), 5398 }, { 5399 name: name("Structs/Inline/Alloc"), 5400 inBuf: `{"E":"","F":"","G":"","A":"","B":"","D":""}`, 5401 inVal: new(structInlined), 5402 want: addr(structInlined{ 5403 X: structInlinedL1{ 5404 X: &structInlinedL2{}, 5405 StructEmbed1: StructEmbed1{}, 5406 }, 5407 StructEmbed2: &StructEmbed2{}, 5408 }), 5409 }, { 5410 name: name("Structs/Inline/NonZero"), 5411 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`, 5412 inVal: new(structInlined), 5413 want: addr(structInlined{ 5414 X: structInlinedL1{ 5415 X: &structInlinedL2{A: "A1", B: "B1" /* C: "C1" */}, 5416 StructEmbed1: StructEmbed1{ /* C: "C2" */ D: "D2" /* E: "E2" */}, 5417 }, 5418 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"}, 5419 }), 5420 }, { 5421 name: name("Structs/Inline/Merge"), 5422 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`, 5423 inVal: addr(structInlined{ 5424 X: structInlinedL1{ 5425 X: &structInlinedL2{B: "##", C: "C1"}, 5426 StructEmbed1: StructEmbed1{C: "C2", E: "E2"}, 5427 }, 5428 StructEmbed2: &StructEmbed2{E: "##", G: "G3"}, 5429 }), 5430 want: addr(structInlined{ 5431 X: structInlinedL1{ 5432 X: &structInlinedL2{A: "A1", B: "B1", C: "C1"}, 5433 StructEmbed1: StructEmbed1{C: "C2", D: "D2", E: "E2"}, 5434 }, 5435 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"}, 5436 }), 5437 }, { 5438 name: name("Structs/InlinedFallback/RawValue/Noop"), 5439 inBuf: `{"A":1,"B":2}`, 5440 inVal: new(structInlineRawValue), 5441 want: addr(structInlineRawValue{A: 1, X: RawValue(nil), B: 2}), 5442 }, { 5443 name: name("Structs/InlinedFallback/RawValue/MergeN1/Nil"), 5444 inBuf: `{"A":1,"fizz":"buzz","B":2}`, 5445 inVal: new(structInlineRawValue), 5446 want: addr(structInlineRawValue{A: 1, X: RawValue(`{"fizz":"buzz"}`), B: 2}), 5447 }, { 5448 name: name("Structs/InlinedFallback/RawValue/MergeN1/Empty"), 5449 inBuf: `{"A":1,"fizz":"buzz","B":2}`, 5450 inVal: addr(structInlineRawValue{X: RawValue{}}), 5451 want: addr(structInlineRawValue{A: 1, X: RawValue(`{"fizz":"buzz"}`), B: 2}), 5452 }, { 5453 name: name("Structs/InlinedFallback/RawValue/MergeN1/Whitespace"), 5454 inBuf: `{"A":1,"fizz":"buzz","B":2}`, 5455 inVal: addr(structInlineRawValue{X: RawValue("\n\r\t ")}), 5456 want: addr(structInlineRawValue{A: 1, X: RawValue("")}), 5457 wantErr: &SemanticError{action: "unmarshal", GoType: rawValueType, Err: errors.New("inlined raw value must be a JSON object")}, 5458 }, { 5459 name: name("Structs/InlinedFallback/RawValue/MergeN1/Null"), 5460 inBuf: `{"A":1,"fizz":"buzz","B":2}`, 5461 inVal: addr(structInlineRawValue{X: RawValue("null")}), 5462 want: addr(structInlineRawValue{A: 1, X: RawValue("null")}), 5463 wantErr: &SemanticError{action: "unmarshal", GoType: rawValueType, Err: errors.New("inlined raw value must be a JSON object")}, 5464 }, { 5465 name: name("Structs/InlinedFallback/RawValue/MergeN1/ObjectN0"), 5466 inBuf: `{"A":1,"fizz":"buzz","B":2}`, 5467 inVal: addr(structInlineRawValue{X: RawValue(` { } `)}), 5468 want: addr(structInlineRawValue{A: 1, X: RawValue(` {"fizz":"buzz"}`), B: 2}), 5469 }, { 5470 name: name("Structs/InlinedFallback/RawValue/MergeN2/ObjectN1"), 5471 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`, 5472 inVal: addr(structInlineRawValue{X: RawValue(` { "fizz" : "buzz" } `)}), 5473 want: addr(structInlineRawValue{A: 1, X: RawValue(` { "fizz" : "buzz","fizz":"buzz","foo":[ 1 , 2 , 3 ]}`), B: 2}), 5474 }, { 5475 name: name("Structs/InlinedFallback/RawValue/Merge/ObjectEnd"), 5476 inBuf: `{"A":1,"fizz":"buzz","B":2}`, 5477 inVal: addr(structInlineRawValue{X: RawValue(` } `)}), 5478 // NOTE: This produces invalid output, 5479 // but the value being merged into is already invalid. 5480 want: addr(structInlineRawValue{A: 1, X: RawValue(`,"fizz":"buzz"}`), B: 2}), 5481 }, { 5482 name: name("Structs/InlinedFallback/RawValue/MergeInvalidValue"), 5483 inBuf: `{"A":1,"fizz":nil,"B":2}`, 5484 inVal: new(structInlineRawValue), 5485 want: addr(structInlineRawValue{A: 1, X: RawValue(`{"fizz":`)}), 5486 wantErr: newInvalidCharacterError([]byte("i"), "within literal null (expecting 'u')").withOffset(int64(len(`{"A":1,"fizz":n`))), 5487 }, { 5488 name: name("Structs/InlinedFallback/RawValue/CaseSensitive"), 5489 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`, 5490 inVal: new(structInlineRawValue), 5491 want: addr(structInlineRawValue{A: 1, X: RawValue(`{"fizz":"buzz","a":3}`), B: 2}), 5492 }, { 5493 name: name("Structs/InlinedFallback/RawValue/RejectDuplicateNames"), 5494 dopts: DecodeOptions{AllowDuplicateNames: false}, 5495 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`, 5496 inVal: new(structInlineRawValue), 5497 want: addr(structInlineRawValue{A: 1, X: RawValue(`{"fizz":"buzz"}`), B: 2}), 5498 wantErr: (&SyntacticError{str: `duplicate name "fizz" in object`}).withOffset(int64(len(`{"A":1,"fizz":"buzz","B":2,`))), 5499 }, { 5500 name: name("Structs/InlinedFallback/RawValue/AllowDuplicateNames"), 5501 dopts: DecodeOptions{AllowDuplicateNames: true}, 5502 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`, 5503 inVal: new(structInlineRawValue), 5504 want: addr(structInlineRawValue{A: 1, X: RawValue(`{"fizz":"buzz","fizz":"buzz"}`), B: 2}), 5505 }, { 5506 name: name("Structs/InlinedFallback/RawValue/Nested/Noop"), 5507 inBuf: `{}`, 5508 inVal: new(structInlinePointerInlineRawValue), 5509 want: new(structInlinePointerInlineRawValue), 5510 }, { 5511 name: name("Structs/InlinedFallback/RawValue/Nested/Alloc"), 5512 inBuf: `{"A":1,"fizz":"buzz"}`, 5513 inVal: new(structInlinePointerInlineRawValue), 5514 want: addr(structInlinePointerInlineRawValue{ 5515 X: &struct { 5516 A int 5517 X RawValue `json:",inline"` 5518 }{A: 1, X: RawValue(`{"fizz":"buzz"}`)}, 5519 }), 5520 }, { 5521 name: name("Structs/InlinedFallback/RawValue/Nested/Merge"), 5522 inBuf: `{"fizz":"buzz"}`, 5523 inVal: addr(structInlinePointerInlineRawValue{ 5524 X: &struct { 5525 A int 5526 X RawValue `json:",inline"` 5527 }{A: 1}, 5528 }), 5529 want: addr(structInlinePointerInlineRawValue{ 5530 X: &struct { 5531 A int 5532 X RawValue `json:",inline"` 5533 }{A: 1, X: RawValue(`{"fizz":"buzz"}`)}, 5534 }), 5535 }, { 5536 name: name("Structs/InlinedFallback/PointerRawValue/Noop"), 5537 inBuf: `{"A":1,"B":2}`, 5538 inVal: new(structInlinePointerRawValue), 5539 want: addr(structInlinePointerRawValue{A: 1, X: nil, B: 2}), 5540 }, { 5541 name: name("Structs/InlinedFallback/PointerRawValue/Alloc"), 5542 inBuf: `{"A":1,"fizz":"buzz","B":2}`, 5543 inVal: new(structInlinePointerRawValue), 5544 want: addr(structInlinePointerRawValue{A: 1, X: addr(RawValue(`{"fizz":"buzz"}`)), B: 2}), 5545 }, { 5546 name: name("Structs/InlinedFallback/PointerRawValue/Merge"), 5547 inBuf: `{"A":1,"fizz":"buzz","B":2}`, 5548 inVal: addr(structInlinePointerRawValue{X: addr(RawValue(`{"fizz":"buzz"}`))}), 5549 want: addr(structInlinePointerRawValue{A: 1, X: addr(RawValue(`{"fizz":"buzz","fizz":"buzz"}`)), B: 2}), 5550 }, { 5551 name: name("Structs/InlinedFallback/PointerRawValue/Nested/Nil"), 5552 inBuf: `{"fizz":"buzz"}`, 5553 inVal: new(structInlineInlinePointerRawValue), 5554 want: addr(structInlineInlinePointerRawValue{ 5555 X: struct { 5556 X *RawValue `json:",inline"` 5557 }{X: addr(RawValue(`{"fizz":"buzz"}`))}, 5558 }), 5559 }, { 5560 name: name("Structs/InlinedFallback/MapStringAny/Noop"), 5561 inBuf: `{"A":1,"B":2}`, 5562 inVal: new(structInlineMapStringAny), 5563 want: addr(structInlineMapStringAny{A: 1, X: nil, B: 2}), 5564 }, { 5565 name: name("Structs/InlinedFallback/MapStringAny/MergeN1/Nil"), 5566 inBuf: `{"A":1,"fizz":"buzz","B":2}`, 5567 inVal: new(structInlineMapStringAny), 5568 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}), 5569 }, { 5570 name: name("Structs/InlinedFallback/MapStringAny/MergeN1/Empty"), 5571 inBuf: `{"A":1,"fizz":"buzz","B":2}`, 5572 inVal: addr(structInlineMapStringAny{X: jsonObject{}}), 5573 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}), 5574 }, { 5575 name: name("Structs/InlinedFallback/MapStringAny/MergeN1/ObjectN1"), 5576 inBuf: `{"A":1,"fizz":{"charlie":"DELTA","echo":"foxtrot"},"B":2}`, 5577 inVal: addr(structInlineMapStringAny{X: jsonObject{"fizz": jsonObject{ 5578 "alpha": "bravo", 5579 "charlie": "delta", 5580 }}}), 5581 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": jsonObject{ 5582 "alpha": "bravo", 5583 "charlie": "DELTA", 5584 "echo": "foxtrot", 5585 }}, B: 2}), 5586 }, { 5587 name: name("Structs/InlinedFallback/MapStringAny/MergeN2/ObjectN1"), 5588 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`, 5589 inVal: addr(structInlineMapStringAny{X: jsonObject{"fizz": "wuzz"}}), 5590 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz", "foo": jsonArray{1.0, 2.0, 3.0}}, B: 2}), 5591 }, { 5592 name: name("Structs/InlinedFallback/MapStringAny/MergeInvalidValue"), 5593 inBuf: `{"A":1,"fizz":nil,"B":2}`, 5594 inVal: new(structInlineMapStringAny), 5595 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": nil}}), 5596 wantErr: newInvalidCharacterError([]byte("i"), "within literal null (expecting 'u')").withOffset(int64(len(`{"A":1,"fizz":n`))), 5597 }, { 5598 name: name("Structs/InlinedFallback/MapStringAny/MergeInvalidValue/Existing"), 5599 inBuf: `{"A":1,"fizz":nil,"B":2}`, 5600 inVal: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": true}}), 5601 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": true}}), 5602 wantErr: newInvalidCharacterError([]byte("i"), "within literal null (expecting 'u')").withOffset(int64(len(`{"A":1,"fizz":n`))), 5603 }, { 5604 name: name("Structs/InlinedFallback/MapStringAny/CaseSensitive"), 5605 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`, 5606 inVal: new(structInlineMapStringAny), 5607 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz", "a": 3.0}, B: 2}), 5608 }, { 5609 name: name("Structs/InlinedFallback/MapStringAny/RejectDuplicateNames"), 5610 dopts: DecodeOptions{AllowDuplicateNames: false}, 5611 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`, 5612 inVal: new(structInlineMapStringAny), 5613 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}), 5614 wantErr: (&SyntacticError{str: `duplicate name "fizz" in object`}).withOffset(int64(len(`{"A":1,"fizz":"buzz","B":2,`))), 5615 }, { 5616 name: name("Structs/InlinedFallback/MapStringAny/AllowDuplicateNames"), 5617 dopts: DecodeOptions{AllowDuplicateNames: true}, 5618 inBuf: `{"A":1,"fizz":{"one":1,"two":-2},"B":2,"fizz":{"two":2,"three":3}}`, 5619 inVal: new(structInlineMapStringAny), 5620 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": jsonObject{"one": 1.0, "two": 2.0, "three": 3.0}}, B: 2}), 5621 }, { 5622 name: name("Structs/InlinedFallback/MapStringAny/Nested/Noop"), 5623 inBuf: `{}`, 5624 inVal: new(structInlinePointerInlineMapStringAny), 5625 want: new(structInlinePointerInlineMapStringAny), 5626 }, { 5627 name: name("Structs/InlinedFallback/MapStringAny/Nested/Alloc"), 5628 inBuf: `{"A":1,"fizz":"buzz"}`, 5629 inVal: new(structInlinePointerInlineMapStringAny), 5630 want: addr(structInlinePointerInlineMapStringAny{ 5631 X: &struct { 5632 A int 5633 X jsonObject `json:",inline"` 5634 }{A: 1, X: jsonObject{"fizz": "buzz"}}, 5635 }), 5636 }, { 5637 name: name("Structs/InlinedFallback/MapStringAny/Nested/Merge"), 5638 inBuf: `{"fizz":"buzz"}`, 5639 inVal: addr(structInlinePointerInlineMapStringAny{ 5640 X: &struct { 5641 A int 5642 X jsonObject `json:",inline"` 5643 }{A: 1}, 5644 }), 5645 want: addr(structInlinePointerInlineMapStringAny{ 5646 X: &struct { 5647 A int 5648 X jsonObject `json:",inline"` 5649 }{A: 1, X: jsonObject{"fizz": "buzz"}}, 5650 }), 5651 }, { 5652 name: name("Structs/InlinedFallback/MapStringInt/UnmarshalFuncV1"), 5653 uopts: UnmarshalOptions{ 5654 Unmarshalers: UnmarshalFuncV1(func(b []byte, v *any) error { 5655 var err error 5656 *v, err = strconv.ParseFloat(string(bytes.Trim(b, `"`)), 64) 5657 return err 5658 }), 5659 }, 5660 inBuf: `{"D":"1.1","E":"2.2","F":"3.3"}`, 5661 inVal: new(structInlineMapStringAny), 5662 want: addr(structInlineMapStringAny{X: jsonObject{"D": 1.1, "E": 2.2, "F": 3.3}}), 5663 }, { 5664 name: name("Structs/InlinedFallback/PointerMapStringAny/Noop"), 5665 inBuf: `{"A":1,"B":2}`, 5666 inVal: new(structInlinePointerMapStringAny), 5667 want: addr(structInlinePointerMapStringAny{A: 1, X: nil, B: 2}), 5668 }, { 5669 name: name("Structs/InlinedFallback/PointerMapStringAny/Alloc"), 5670 inBuf: `{"A":1,"fizz":"buzz","B":2}`, 5671 inVal: new(structInlinePointerMapStringAny), 5672 want: addr(structInlinePointerMapStringAny{A: 1, X: addr(jsonObject{"fizz": "buzz"}), B: 2}), 5673 }, { 5674 name: name("Structs/InlinedFallback/PointerMapStringAny/Merge"), 5675 inBuf: `{"A":1,"fizz":"wuzz","B":2}`, 5676 inVal: addr(structInlinePointerMapStringAny{X: addr(jsonObject{"fizz": "buzz"})}), 5677 want: addr(structInlinePointerMapStringAny{A: 1, X: addr(jsonObject{"fizz": "wuzz"}), B: 2}), 5678 }, { 5679 name: name("Structs/InlinedFallback/PointerMapStringAny/Nested/Nil"), 5680 inBuf: `{"fizz":"buzz"}`, 5681 inVal: new(structInlineInlinePointerMapStringAny), 5682 want: addr(structInlineInlinePointerMapStringAny{ 5683 X: struct { 5684 X *jsonObject `json:",inline"` 5685 }{X: addr(jsonObject{"fizz": "buzz"})}, 5686 }), 5687 }, { 5688 name: name("Structs/InlinedFallback/MapStringInt"), 5689 inBuf: `{"zero": 0, "one": 1, "two": 2}`, 5690 inVal: new(structInlineMapStringInt), 5691 want: addr(structInlineMapStringInt{ 5692 X: map[string]int{"zero": 0, "one": 1, "two": 2}, 5693 }), 5694 }, { 5695 name: name("Structs/InlinedFallback/MapStringInt/Null"), 5696 inBuf: `{"zero": 0, "one": null, "two": 2}`, 5697 inVal: new(structInlineMapStringInt), 5698 want: addr(structInlineMapStringInt{ 5699 X: map[string]int{"zero": 0, "one": 0, "two": 2}, 5700 }), 5701 }, { 5702 name: name("Structs/InlinedFallback/MapStringInt/Invalid"), 5703 inBuf: `{"zero": 0, "one": {}, "two": 2}`, 5704 inVal: new(structInlineMapStringInt), 5705 want: addr(structInlineMapStringInt{ 5706 X: map[string]int{"zero": 0, "one": 0}, 5707 }), 5708 wantErr: &SemanticError{action: "unmarshal", JSONKind: '{', GoType: intType}, 5709 }, { 5710 name: name("Structs/InlinedFallback/MapStringInt/StringifiedNumbers"), 5711 uopts: UnmarshalOptions{StringifyNumbers: true}, 5712 inBuf: `{"zero": 0, "one": "1", "two": 2}`, 5713 inVal: new(structInlineMapStringInt), 5714 want: addr(structInlineMapStringInt{ 5715 X: map[string]int{"zero": 0, "one": 1, "two": 2}, 5716 }), 5717 }, { 5718 name: name("Structs/InlinedFallback/MapStringInt/UnmarshalFuncV1"), 5719 uopts: UnmarshalOptions{ 5720 Unmarshalers: UnmarshalFuncV1(func(b []byte, v *int) error { 5721 i, err := strconv.ParseInt(string(bytes.Trim(b, `"`)), 10, 64) 5722 if err != nil { 5723 return err 5724 } 5725 *v = int(i) 5726 return nil 5727 }), 5728 }, 5729 inBuf: `{"zero": "0", "one": "1", "two": "2"}`, 5730 inVal: new(structInlineMapStringInt), 5731 want: addr(structInlineMapStringInt{ 5732 X: map[string]int{"zero": 0, "one": 1, "two": 2}, 5733 }), 5734 }, { 5735 name: name("Structs/InlinedFallback/RejectUnknownMembers"), 5736 uopts: UnmarshalOptions{RejectUnknownMembers: true}, 5737 inBuf: `{"A":1,"fizz":"buzz","B":2}`, 5738 inVal: new(structInlineRawValue), 5739 // NOTE: DiscardUnknownMembers has no effect since this is "inline". 5740 want: addr(structInlineRawValue{ 5741 A: 1, 5742 X: RawValue(`{"fizz":"buzz"}`), 5743 B: 2, 5744 }), 5745 }, { 5746 name: name("Structs/UnknownFallback/RejectUnknownMembers"), 5747 uopts: UnmarshalOptions{RejectUnknownMembers: true}, 5748 inBuf: `{"A":1,"fizz":"buzz","B":2}`, 5749 inVal: new(structUnknownRawValue), 5750 want: addr(structUnknownRawValue{A: 1}), 5751 wantErr: &SemanticError{action: "unmarshal", GoType: structUnknownRawValueType, Err: errors.New(`unknown name "fizz"`)}, 5752 }, { 5753 name: name("Structs/UnknownFallback"), 5754 inBuf: `{"A":1,"fizz":"buzz","B":2}`, 5755 inVal: new(structUnknownRawValue), 5756 want: addr(structUnknownRawValue{ 5757 A: 1, 5758 X: RawValue(`{"fizz":"buzz"}`), 5759 B: 2, 5760 }), 5761 }, { 5762 name: name("Structs/UnknownIgnored"), 5763 uopts: UnmarshalOptions{RejectUnknownMembers: false}, 5764 inBuf: `{"unknown":"fizzbuzz"}`, 5765 inVal: new(structAll), 5766 want: new(structAll), 5767 }, { 5768 name: name("Structs/RejectUnknownMembers"), 5769 uopts: UnmarshalOptions{RejectUnknownMembers: true}, 5770 inBuf: `{"unknown":"fizzbuzz"}`, 5771 inVal: new(structAll), 5772 want: new(structAll), 5773 wantErr: &SemanticError{action: "unmarshal", GoType: structAllType, Err: errors.New(`unknown name "unknown"`)}, 5774 }, { 5775 name: name("Structs/UnexportedIgnored"), 5776 inBuf: `{"ignored":"unused"}`, 5777 inVal: new(structUnexportedIgnored), 5778 want: new(structUnexportedIgnored), 5779 }, { 5780 name: name("Structs/IgnoredUnexportedEmbedded"), 5781 inBuf: `{"namedString":"unused"}`, 5782 inVal: new(structIgnoredUnexportedEmbedded), 5783 want: new(structIgnoredUnexportedEmbedded), 5784 }, { 5785 name: name("Structs/WeirdNames"), 5786 inBuf: `{"":"empty",",":"comma","\"":"quote"}`, 5787 inVal: new(structWeirdNames), 5788 want: addr(structWeirdNames{Empty: "empty", Comma: "comma", Quote: "quote"}), 5789 }, { 5790 name: name("Structs/NoCase/Exact"), 5791 inBuf: `{"AaA":"AaA","AAa":"AAa","AAA":"AAA"}`, 5792 inVal: new(structNoCase), 5793 want: addr(structNoCase{AaA: "AaA", AAa: "AAa", AAA: "AAA"}), 5794 }, { 5795 name: name("Structs/NoCase/Merge/AllowDuplicateNames"), 5796 dopts: DecodeOptions{AllowDuplicateNames: true}, 5797 inBuf: `{"AaA":"AaA","aaa":"aaa","aAa":"aAa"}`, 5798 inVal: new(structNoCase), 5799 want: addr(structNoCase{AaA: "aAa"}), 5800 }, { 5801 name: name("Structs/NoCase/Merge/RejectDuplicateNames"), 5802 dopts: DecodeOptions{AllowDuplicateNames: false}, 5803 inBuf: `{"AaA":"AaA","aaa":"aaa"}`, 5804 inVal: new(structNoCase), 5805 want: addr(structNoCase{AaA: "AaA"}), 5806 wantErr: (&SyntacticError{str: `duplicate name "aaa" in object`}).withOffset(int64(len(`{"AaA":"AaA",`))), 5807 }, { 5808 name: name("Structs/CaseSensitive"), 5809 inBuf: `{"BOOL": true, "STRING": "hello", "BYTES": "AQID", "INT": -64, "UINT": 64, "FLOAT": 3.14159}`, 5810 inVal: new(structScalars), 5811 want: addr(structScalars{}), 5812 }, { 5813 name: name("Structs/DuplicateName/NoCase/ExactDifferent"), 5814 inBuf: `{"AAA":"AAA","AaA":"AaA","AAa":"AAa","Aaa":"Aaa"}`, 5815 inVal: addr(structNoCaseInlineRawValue{}), 5816 want: addr(structNoCaseInlineRawValue{AAA: "AAA", AaA: "AaA", AAa: "AAa", Aaa: "Aaa"}), 5817 }, { 5818 name: name("Structs/DuplicateName/NoCase/ExactConflict"), 5819 inBuf: `{"AAA":"AAA","AAA":"AAA"}`, 5820 inVal: addr(structNoCaseInlineRawValue{}), 5821 want: addr(structNoCaseInlineRawValue{AAA: "AAA"}), 5822 wantErr: (&SyntacticError{str: `duplicate name "AAA" in object`}).withOffset(int64(len(`{"AAA":"AAA",`))), 5823 }, { 5824 name: name("Structs/DuplicateName/NoCase/OverwriteExact"), 5825 inBuf: `{"AAA":"after"}`, 5826 inVal: addr(structNoCaseInlineRawValue{AAA: "before"}), 5827 want: addr(structNoCaseInlineRawValue{AAA: "after"}), 5828 }, { 5829 name: name("Structs/DuplicateName/NoCase/NoCaseConflict"), 5830 inBuf: `{"aaa":"aaa","aaA":"aaA"}`, 5831 inVal: addr(structNoCaseInlineRawValue{}), 5832 want: addr(structNoCaseInlineRawValue{AaA: "aaa"}), 5833 wantErr: (&SyntacticError{str: `duplicate name "aaA" in object`}).withOffset(int64(len(`{"aaa":"aaa",`))), 5834 }, { 5835 name: name("Structs/DuplicateName/NoCase/OverwriteNoCase"), 5836 inBuf: `{"aaa":"aaa","aaA":"aaA"}`, 5837 inVal: addr(structNoCaseInlineRawValue{}), 5838 want: addr(structNoCaseInlineRawValue{AaA: "aaa"}), 5839 wantErr: (&SyntacticError{str: `duplicate name "aaA" in object`}).withOffset(int64(len(`{"aaa":"aaa",`))), 5840 }, { 5841 name: name("Structs/DuplicateName/Inline/Unknown"), 5842 inBuf: `{"unknown":""}`, 5843 inVal: addr(structNoCaseInlineRawValue{}), 5844 want: addr(structNoCaseInlineRawValue{X: RawValue(`{"unknown":""}`)}), 5845 }, { 5846 name: name("Structs/DuplicateName/Inline/UnknownMerge"), 5847 inBuf: `{"unknown":""}`, 5848 inVal: addr(structNoCaseInlineRawValue{X: RawValue(`{"unknown":""}`)}), 5849 want: addr(structNoCaseInlineRawValue{X: RawValue(`{"unknown":"","unknown":""}`)}), 5850 }, { 5851 name: name("Structs/DuplicateName/Inline/NoCaseOkay"), 5852 inBuf: `{"b":"","B":""}`, 5853 inVal: addr(structNoCaseInlineRawValue{}), 5854 want: addr(structNoCaseInlineRawValue{X: RawValue(`{"b":"","B":""}`)}), 5855 }, { 5856 name: name("Structs/DuplicateName/Inline/ExactConflict"), 5857 inBuf: `{"b":"","b":""}`, 5858 inVal: addr(structNoCaseInlineRawValue{}), 5859 want: addr(structNoCaseInlineRawValue{X: RawValue(`{"b":""}`)}), 5860 wantErr: (&SyntacticError{str: `duplicate name "b" in object`}).withOffset(int64(len(`{"b":"",`))), 5861 }, { 5862 name: name("Structs/Invalid/ErrUnexpectedEOF"), 5863 inBuf: ``, 5864 inVal: addr(structAll{}), 5865 want: addr(structAll{}), 5866 wantErr: io.ErrUnexpectedEOF, 5867 }, { 5868 name: name("Structs/Invalid/NestedErrUnexpectedEOF"), 5869 inBuf: `{"Pointer":`, 5870 inVal: addr(structAll{}), 5871 want: addr(structAll{Pointer: new(structAll)}), 5872 wantErr: io.ErrUnexpectedEOF, 5873 }, { 5874 name: name("Structs/Invalid/Conflicting"), 5875 inBuf: `{}`, 5876 inVal: addr(structConflicting{}), 5877 want: addr(structConflicting{}), 5878 wantErr: &SemanticError{action: "unmarshal", GoType: structConflictingType, Err: errors.New("Go struct fields A and B conflict over JSON object name \"conflict\"")}, 5879 }, { 5880 name: name("Structs/Invalid/NoneExported"), 5881 inBuf: `{}`, 5882 inVal: addr(structNoneExported{}), 5883 want: addr(structNoneExported{}), 5884 wantErr: &SemanticError{action: "unmarshal", GoType: structNoneExportedType, Err: errors.New("Go struct has no exported fields")}, 5885 }, { 5886 name: name("Structs/Invalid/MalformedTag"), 5887 inBuf: `{}`, 5888 inVal: addr(structMalformedTag{}), 5889 want: addr(structMalformedTag{}), 5890 wantErr: &SemanticError{action: "unmarshal", GoType: structMalformedTagType, Err: errors.New("Go struct field Malformed has malformed `json` tag: invalid character '\"' at start of option (expecting Unicode letter or single quote)")}, 5891 }, { 5892 name: name("Structs/Invalid/UnexportedTag"), 5893 inBuf: `{}`, 5894 inVal: addr(structUnexportedTag{}), 5895 want: addr(structUnexportedTag{}), 5896 wantErr: &SemanticError{action: "unmarshal", GoType: structUnexportedTagType, Err: errors.New("unexported Go struct field unexported cannot have non-ignored `json:\"name\"` tag")}, 5897 }, { 5898 name: name("Structs/Invalid/UnexportedEmbedded"), 5899 inBuf: `{}`, 5900 inVal: addr(structUnexportedEmbedded{}), 5901 want: addr(structUnexportedEmbedded{}), 5902 wantErr: &SemanticError{action: "unmarshal", GoType: structUnexportedEmbeddedType, Err: errors.New("embedded Go struct field namedString of an unexported type must be explicitly ignored with a `json:\"-\"` tag")}, 5903 }, { 5904 name: name("Structs/Unknown"), 5905 inBuf: `{ 5906 "object0": {}, 5907 "object1": {"key1": "value"}, 5908 "object2": {"key1": "value", "key2": "value"}, 5909 "objects": {"":{"":{"":{}}}}, 5910 "array0": [], 5911 "array1": ["value1"], 5912 "array2": ["value1", "value2"], 5913 "array": [[[]]], 5914 "scalars": [null, false, true, "string", 12.345] 5915 }`, 5916 inVal: addr(struct{}{}), 5917 want: addr(struct{}{}), 5918 }, { 5919 name: name("Structs/IgnoreInvalidFormat"), 5920 uopts: UnmarshalOptions{formatDepth: 1000, format: "invalid"}, 5921 inBuf: `{"Field":"Value"}`, 5922 inVal: addr(struct{ Field string }{}), 5923 want: addr(struct{ Field string }{"Value"}), 5924 }, { 5925 name: name("Slices/Null"), 5926 inBuf: `null`, 5927 inVal: addr([]string{"something"}), 5928 want: addr([]string(nil)), 5929 }, { 5930 name: name("Slices/Bool"), 5931 inBuf: `[true,false]`, 5932 inVal: new([]bool), 5933 want: addr([]bool{true, false}), 5934 }, { 5935 name: name("Slices/String"), 5936 inBuf: `["hello","goodbye"]`, 5937 inVal: new([]string), 5938 want: addr([]string{"hello", "goodbye"}), 5939 }, { 5940 name: name("Slices/Bytes"), 5941 inBuf: `["aGVsbG8=","Z29vZGJ5ZQ=="]`, 5942 inVal: new([][]byte), 5943 want: addr([][]byte{[]byte("hello"), []byte("goodbye")}), 5944 }, { 5945 name: name("Slices/Int"), 5946 inBuf: `[-2,-1,0,1,2]`, 5947 inVal: new([]int), 5948 want: addr([]int{-2, -1, 0, 1, 2}), 5949 }, { 5950 name: name("Slices/Uint"), 5951 inBuf: `[0,1,2,3,4]`, 5952 inVal: new([]uint), 5953 want: addr([]uint{0, 1, 2, 3, 4}), 5954 }, { 5955 name: name("Slices/Float"), 5956 inBuf: `[3.14159,12.34]`, 5957 inVal: new([]float64), 5958 want: addr([]float64{3.14159, 12.34}), 5959 }, { 5960 // NOTE: The semantics differs from v1, where the slice length is reset 5961 // and new elements are appended to the end. 5962 // See https://go.dev/issue/21092. 5963 name: name("Slices/Merge"), 5964 inBuf: `[{"k3":"v3"},{"k4":"v4"}]`, 5965 inVal: addr([]map[string]string{{"k1": "v1"}, {"k2": "v2"}}[:1]), 5966 want: addr([]map[string]string{{"k3": "v3"}, {"k4": "v4"}}), 5967 }, { 5968 name: name("Slices/Invalid/Channel"), 5969 inBuf: `["hello"]`, 5970 inVal: new([]chan string), 5971 want: addr([]chan string{nil}), 5972 wantErr: &SemanticError{action: "unmarshal", GoType: chanStringType}, 5973 }, { 5974 name: name("Slices/RecursiveSlice"), 5975 inBuf: `[[],[],[[]],[[],[]]]`, 5976 inVal: new(recursiveSlice), 5977 want: addr(recursiveSlice{ 5978 {}, 5979 {}, 5980 {{}}, 5981 {{}, {}}, 5982 }), 5983 }, { 5984 name: name("Slices/Invalid/Bool"), 5985 inBuf: `true`, 5986 inVal: addr([]string{"nochange"}), 5987 want: addr([]string{"nochange"}), 5988 wantErr: &SemanticError{action: "unmarshal", JSONKind: 't', GoType: sliceStringType}, 5989 }, { 5990 name: name("Slices/Invalid/String"), 5991 inBuf: `""`, 5992 inVal: addr([]string{"nochange"}), 5993 want: addr([]string{"nochange"}), 5994 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: sliceStringType}, 5995 }, { 5996 name: name("Slices/Invalid/Number"), 5997 inBuf: `0`, 5998 inVal: addr([]string{"nochange"}), 5999 want: addr([]string{"nochange"}), 6000 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: sliceStringType}, 6001 }, { 6002 name: name("Slices/Invalid/Object"), 6003 inBuf: `{}`, 6004 inVal: addr([]string{"nochange"}), 6005 want: addr([]string{"nochange"}), 6006 wantErr: &SemanticError{action: "unmarshal", JSONKind: '{', GoType: sliceStringType}, 6007 }, { 6008 name: name("Slices/IgnoreInvalidFormat"), 6009 uopts: UnmarshalOptions{formatDepth: 1000, format: "invalid"}, 6010 inBuf: `[false,true]`, 6011 inVal: addr([]bool{true, false}), 6012 want: addr([]bool{false, true}), 6013 }, { 6014 name: name("Arrays/Null"), 6015 inBuf: `null`, 6016 inVal: addr([1]string{"something"}), 6017 want: addr([1]string{}), 6018 }, { 6019 name: name("Arrays/Bool"), 6020 inBuf: `[true,false]`, 6021 inVal: new([2]bool), 6022 want: addr([2]bool{true, false}), 6023 }, { 6024 name: name("Arrays/String"), 6025 inBuf: `["hello","goodbye"]`, 6026 inVal: new([2]string), 6027 want: addr([2]string{"hello", "goodbye"}), 6028 }, { 6029 name: name("Arrays/Bytes"), 6030 inBuf: `["aGVsbG8=","Z29vZGJ5ZQ=="]`, 6031 inVal: new([2][]byte), 6032 want: addr([2][]byte{[]byte("hello"), []byte("goodbye")}), 6033 }, { 6034 name: name("Arrays/Int"), 6035 inBuf: `[-2,-1,0,1,2]`, 6036 inVal: new([5]int), 6037 want: addr([5]int{-2, -1, 0, 1, 2}), 6038 }, { 6039 name: name("Arrays/Uint"), 6040 inBuf: `[0,1,2,3,4]`, 6041 inVal: new([5]uint), 6042 want: addr([5]uint{0, 1, 2, 3, 4}), 6043 }, { 6044 name: name("Arrays/Float"), 6045 inBuf: `[3.14159,12.34]`, 6046 inVal: new([2]float64), 6047 want: addr([2]float64{3.14159, 12.34}), 6048 }, { 6049 // NOTE: The semantics differs from v1, where elements are not merged. 6050 // This is to maintain consistent merge semantics with slices. 6051 name: name("Arrays/Merge"), 6052 inBuf: `[{"k3":"v3"},{"k4":"v4"}]`, 6053 inVal: addr([2]map[string]string{{"k1": "v1"}, {"k2": "v2"}}), 6054 want: addr([2]map[string]string{{"k3": "v3"}, {"k4": "v4"}}), 6055 }, { 6056 name: name("Arrays/Invalid/Channel"), 6057 inBuf: `["hello"]`, 6058 inVal: new([1]chan string), 6059 want: new([1]chan string), 6060 wantErr: &SemanticError{action: "unmarshal", GoType: chanStringType}, 6061 }, { 6062 name: name("Arrays/Invalid/Underflow"), 6063 inBuf: `[]`, 6064 inVal: new([1]string), 6065 want: addr([1]string{}), 6066 wantErr: &SemanticError{action: "unmarshal", GoType: array1StringType, Err: errors.New("too few array elements")}, 6067 }, { 6068 name: name("Arrays/Invalid/Overflow"), 6069 inBuf: `["1","2"]`, 6070 inVal: new([1]string), 6071 want: addr([1]string{"1"}), 6072 wantErr: &SemanticError{action: "unmarshal", GoType: array1StringType, Err: errors.New("too many array elements")}, 6073 }, { 6074 name: name("Arrays/Invalid/Bool"), 6075 inBuf: `true`, 6076 inVal: addr([1]string{"nochange"}), 6077 want: addr([1]string{"nochange"}), 6078 wantErr: &SemanticError{action: "unmarshal", JSONKind: 't', GoType: array1StringType}, 6079 }, { 6080 name: name("Arrays/Invalid/String"), 6081 inBuf: `""`, 6082 inVal: addr([1]string{"nochange"}), 6083 want: addr([1]string{"nochange"}), 6084 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: array1StringType}, 6085 }, { 6086 name: name("Arrays/Invalid/Number"), 6087 inBuf: `0`, 6088 inVal: addr([1]string{"nochange"}), 6089 want: addr([1]string{"nochange"}), 6090 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: array1StringType}, 6091 }, { 6092 name: name("Arrays/Invalid/Object"), 6093 inBuf: `{}`, 6094 inVal: addr([1]string{"nochange"}), 6095 want: addr([1]string{"nochange"}), 6096 wantErr: &SemanticError{action: "unmarshal", JSONKind: '{', GoType: array1StringType}, 6097 }, { 6098 name: name("Arrays/IgnoreInvalidFormat"), 6099 uopts: UnmarshalOptions{formatDepth: 1000, format: "invalid"}, 6100 inBuf: `[false,true]`, 6101 inVal: addr([2]bool{true, false}), 6102 want: addr([2]bool{false, true}), 6103 }, { 6104 name: name("Pointers/NullL0"), 6105 inBuf: `null`, 6106 inVal: new(*string), 6107 want: addr((*string)(nil)), 6108 }, { 6109 name: name("Pointers/NullL1"), 6110 inBuf: `null`, 6111 inVal: addr(new(*string)), 6112 want: addr((**string)(nil)), 6113 }, { 6114 name: name("Pointers/Bool"), 6115 inBuf: `true`, 6116 inVal: addr(new(bool)), 6117 want: addr(addr(true)), 6118 }, { 6119 name: name("Pointers/String"), 6120 inBuf: `"hello"`, 6121 inVal: addr(new(string)), 6122 want: addr(addr("hello")), 6123 }, { 6124 name: name("Pointers/Bytes"), 6125 inBuf: `"aGVsbG8="`, 6126 inVal: addr(new([]byte)), 6127 want: addr(addr([]byte("hello"))), 6128 }, { 6129 name: name("Pointers/Int"), 6130 inBuf: `-123`, 6131 inVal: addr(new(int)), 6132 want: addr(addr(int(-123))), 6133 }, { 6134 name: name("Pointers/Uint"), 6135 inBuf: `123`, 6136 inVal: addr(new(int)), 6137 want: addr(addr(int(123))), 6138 }, { 6139 name: name("Pointers/Float"), 6140 inBuf: `123.456`, 6141 inVal: addr(new(float64)), 6142 want: addr(addr(float64(123.456))), 6143 }, { 6144 name: name("Pointers/Allocate"), 6145 inBuf: `"hello"`, 6146 inVal: addr((*string)(nil)), 6147 want: addr(addr("hello")), 6148 }, { 6149 name: name("Points/IgnoreInvalidFormat"), 6150 uopts: UnmarshalOptions{formatDepth: 1000, format: "invalid"}, 6151 inBuf: `true`, 6152 inVal: addr(new(bool)), 6153 want: addr(addr(true)), 6154 }, { 6155 name: name("Interfaces/Empty/Null"), 6156 inBuf: `null`, 6157 inVal: new(any), 6158 want: new(any), 6159 }, { 6160 name: name("Interfaces/NonEmpty/Null"), 6161 inBuf: `null`, 6162 inVal: new(io.Reader), 6163 want: new(io.Reader), 6164 }, { 6165 name: name("Interfaces/NonEmpty/Invalid"), 6166 inBuf: `"hello"`, 6167 inVal: new(io.Reader), 6168 want: new(io.Reader), 6169 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: ioReaderType, Err: errors.New("cannot derive concrete type for non-empty interface")}, 6170 }, { 6171 name: name("Interfaces/Empty/False"), 6172 inBuf: `false`, 6173 inVal: new(any), 6174 want: func() any { 6175 var vi any = false 6176 return &vi 6177 }(), 6178 }, { 6179 name: name("Interfaces/Empty/True"), 6180 inBuf: `true`, 6181 inVal: new(any), 6182 want: func() any { 6183 var vi any = true 6184 return &vi 6185 }(), 6186 }, { 6187 name: name("Interfaces/Empty/String"), 6188 inBuf: `"string"`, 6189 inVal: new(any), 6190 want: func() any { 6191 var vi any = "string" 6192 return &vi 6193 }(), 6194 }, { 6195 name: name("Interfaces/Empty/Number"), 6196 inBuf: `3.14159`, 6197 inVal: new(any), 6198 want: func() any { 6199 var vi any = 3.14159 6200 return &vi 6201 }(), 6202 }, { 6203 name: name("Interfaces/Empty/Object"), 6204 inBuf: `{"k":"v"}`, 6205 inVal: new(any), 6206 want: func() any { 6207 var vi any = map[string]any{"k": "v"} 6208 return &vi 6209 }(), 6210 }, { 6211 name: name("Interfaces/Empty/Array"), 6212 inBuf: `["v"]`, 6213 inVal: new(any), 6214 want: func() any { 6215 var vi any = []any{"v"} 6216 return &vi 6217 }(), 6218 }, { 6219 name: name("Interfaces/NamedAny/String"), 6220 inBuf: `"string"`, 6221 inVal: new(namedAny), 6222 want: func() namedAny { 6223 var vi namedAny = "string" 6224 return &vi 6225 }(), 6226 }, { 6227 name: name("Interfaces/Invalid"), 6228 inBuf: `]`, 6229 inVal: new(any), 6230 want: new(any), 6231 wantErr: newInvalidCharacterError([]byte("]"), "at start of value"), 6232 }, { 6233 // NOTE: The semantics differs from v1, 6234 // where existing map entries were not merged into. 6235 // See https://go.dev/issue/26946. 6236 // See https://go.dev/issue/33993. 6237 name: name("Interfaces/Merge/Map"), 6238 inBuf: `{"k2":"v2"}`, 6239 inVal: func() any { 6240 var vi any = map[string]string{"k1": "v1"} 6241 return &vi 6242 }(), 6243 want: func() any { 6244 var vi any = map[string]string{"k1": "v1", "k2": "v2"} 6245 return &vi 6246 }(), 6247 }, { 6248 name: name("Interfaces/Merge/Struct"), 6249 inBuf: `{"Array":["goodbye"]}`, 6250 inVal: func() any { 6251 var vi any = structAll{String: "hello"} 6252 return &vi 6253 }(), 6254 want: func() any { 6255 var vi any = structAll{String: "hello", Array: [1]string{"goodbye"}} 6256 return &vi 6257 }(), 6258 }, { 6259 name: name("Interfaces/Merge/NamedInt"), 6260 inBuf: `64`, 6261 inVal: func() any { 6262 var vi any = namedInt64(-64) 6263 return &vi 6264 }(), 6265 want: func() any { 6266 var vi any = namedInt64(+64) 6267 return &vi 6268 }(), 6269 }, { 6270 name: name("Interfaces/IgnoreInvalidFormat"), 6271 uopts: UnmarshalOptions{formatDepth: 1000, format: "invalid"}, 6272 inBuf: `true`, 6273 inVal: new(any), 6274 want: func() any { 6275 var vi any = true 6276 return &vi 6277 }(), 6278 }, { 6279 name: name("Interfaces/Any"), 6280 inBuf: `{"X":[null,false,true,"",0,{},[]]}`, 6281 inVal: new(struct{ X any }), 6282 want: addr(struct{ X any }{[]any{nil, false, true, "", 0.0, map[string]any{}, []any{}}}), 6283 }, { 6284 name: name("Interfaces/Any/Named"), 6285 inBuf: `{"X":[null,false,true,"",0,{},[]]}`, 6286 inVal: new(struct{ X namedAny }), 6287 want: addr(struct{ X namedAny }{[]any{nil, false, true, "", 0.0, map[string]any{}, []any{}}}), 6288 }, { 6289 name: name("Interfaces/Any/Stringified"), 6290 uopts: UnmarshalOptions{StringifyNumbers: true}, 6291 inBuf: `{"X":"0"}`, 6292 inVal: new(struct{ X any }), 6293 want: addr(struct{ X any }{"0"}), 6294 }, { 6295 name: name("Interfaces/Any/UnmarshalFunc/Any"), 6296 uopts: UnmarshalOptions{Unmarshalers: UnmarshalFuncV1(func(b []byte, v *any) error { 6297 *v = "called" 6298 return nil 6299 })}, 6300 inBuf: `{"X":[null,false,true,"",0,{},[]]}`, 6301 inVal: new(struct{ X any }), 6302 want: addr(struct{ X any }{"called"}), 6303 }, { 6304 name: name("Interfaces/Any/UnmarshalFunc/Bool"), 6305 uopts: UnmarshalOptions{Unmarshalers: UnmarshalFuncV1(func(b []byte, v *bool) error { 6306 *v = string(b) != "true" 6307 return nil 6308 })}, 6309 inBuf: `{"X":[null,false,true,"",0,{},[]]}`, 6310 inVal: new(struct{ X any }), 6311 want: addr(struct{ X any }{[]any{nil, true, false, "", 0.0, map[string]any{}, []any{}}}), 6312 }, { 6313 name: name("Interfaces/Any/UnmarshalFunc/String"), 6314 uopts: UnmarshalOptions{Unmarshalers: UnmarshalFuncV1(func(b []byte, v *string) error { 6315 *v = "called" 6316 return nil 6317 })}, 6318 inBuf: `{"X":[null,false,true,"",0,{},[]]}`, 6319 inVal: new(struct{ X any }), 6320 want: addr(struct{ X any }{[]any{nil, false, true, "called", 0.0, map[string]any{}, []any{}}}), 6321 }, { 6322 name: name("Interfaces/Any/UnmarshalFunc/Float64"), 6323 uopts: UnmarshalOptions{Unmarshalers: UnmarshalFuncV1(func(b []byte, v *float64) error { 6324 *v = 3.14159 6325 return nil 6326 })}, 6327 inBuf: `{"X":[null,false,true,"",0,{},[]]}`, 6328 inVal: new(struct{ X any }), 6329 want: addr(struct{ X any }{[]any{nil, false, true, "", 3.14159, map[string]any{}, []any{}}}), 6330 }, { 6331 name: name("Interfaces/Any/UnmarshalFunc/MapStringAny"), 6332 uopts: UnmarshalOptions{Unmarshalers: UnmarshalFuncV1(func(b []byte, v *map[string]any) error { 6333 *v = map[string]any{"called": nil} 6334 return nil 6335 })}, 6336 inBuf: `{"X":[null,false,true,"",0,{},[]]}`, 6337 inVal: new(struct{ X any }), 6338 want: addr(struct{ X any }{[]any{nil, false, true, "", 0.0, map[string]any{"called": nil}, []any{}}}), 6339 }, { 6340 name: name("Interfaces/Any/UnmarshalFunc/SliceAny"), 6341 uopts: UnmarshalOptions{Unmarshalers: UnmarshalFuncV1(func(b []byte, v *[]any) error { 6342 *v = []any{"called"} 6343 return nil 6344 })}, 6345 inBuf: `{"X":[null,false,true,"",0,{},[]]}`, 6346 inVal: new(struct{ X any }), 6347 want: addr(struct{ X any }{[]any{"called"}}), 6348 }, { 6349 name: name("Interfaces/Any/Maps/NonEmpty"), 6350 inBuf: `{"X":{"fizz":"buzz"}}`, 6351 inVal: new(struct{ X any }), 6352 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}), 6353 }, { 6354 name: name("Interfaces/Any/Maps/RejectDuplicateNames"), 6355 inBuf: `{"X":{"fizz":"buzz","fizz":true}}`, 6356 inVal: new(struct{ X any }), 6357 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}), 6358 wantErr: (&SyntacticError{str: `duplicate name "fizz" in object`}).withOffset(int64(len(`{"X":{"fizz":"buzz",`))), 6359 }, { 6360 name: name("Interfaces/Any/Maps/AllowDuplicateNames"), 6361 dopts: DecodeOptions{AllowDuplicateNames: true}, 6362 inBuf: `{"X":{"fizz":"buzz","fizz":true}}`, 6363 inVal: new(struct{ X any }), 6364 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}), 6365 wantErr: &SemanticError{action: "unmarshal", JSONKind: 't', GoType: stringType}, 6366 }, { 6367 name: name("Interfaces/Any/Slices/NonEmpty"), 6368 inBuf: `{"X":["fizz","buzz"]}`, 6369 inVal: new(struct{ X any }), 6370 want: addr(struct{ X any }{[]any{"fizz", "buzz"}}), 6371 }, { 6372 name: name("Methods/NilPointer/Null"), 6373 inBuf: `{"X":null}`, 6374 inVal: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}), 6375 want: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}), // method should not be called 6376 }, { 6377 name: name("Methods/NilPointer/Value"), 6378 inBuf: `{"X":"value"}`, 6379 inVal: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}), 6380 want: addr(struct{ X *allMethods }{X: &allMethods{method: "UnmarshalNextJSON", value: []byte(`"value"`)}}), 6381 }, { 6382 name: name("Methods/NilInterface/Null"), 6383 inBuf: `{"X":null}`, 6384 inVal: addr(struct{ X MarshalerV2 }{X: (*allMethods)(nil)}), 6385 want: addr(struct{ X MarshalerV2 }{X: nil}), // interface value itself is nil'd out 6386 }, { 6387 name: name("Methods/NilInterface/Value"), 6388 inBuf: `{"X":"value"}`, 6389 inVal: addr(struct{ X MarshalerV2 }{X: (*allMethods)(nil)}), 6390 want: addr(struct{ X MarshalerV2 }{X: &allMethods{method: "UnmarshalNextJSON", value: []byte(`"value"`)}}), 6391 }, { 6392 name: name("Methods/AllMethods"), 6393 inBuf: `{"X":"hello"}`, 6394 inVal: new(struct{ X *allMethods }), 6395 want: addr(struct{ X *allMethods }{X: &allMethods{method: "UnmarshalNextJSON", value: []byte(`"hello"`)}}), 6396 }, { 6397 name: name("Methods/AllMethodsExceptJSONv2"), 6398 inBuf: `{"X":"hello"}`, 6399 inVal: new(struct{ X *allMethodsExceptJSONv2 }), 6400 want: addr(struct{ X *allMethodsExceptJSONv2 }{X: &allMethodsExceptJSONv2{allMethods: allMethods{method: "UnmarshalJSON", value: []byte(`"hello"`)}}}), 6401 }, { 6402 name: name("Methods/AllMethodsExceptJSONv1"), 6403 inBuf: `{"X":"hello"}`, 6404 inVal: new(struct{ X *allMethodsExceptJSONv1 }), 6405 want: addr(struct{ X *allMethodsExceptJSONv1 }{X: &allMethodsExceptJSONv1{allMethods: allMethods{method: "UnmarshalNextJSON", value: []byte(`"hello"`)}}}), 6406 }, { 6407 name: name("Methods/AllMethodsExceptText"), 6408 inBuf: `{"X":"hello"}`, 6409 inVal: new(struct{ X *allMethodsExceptText }), 6410 want: addr(struct{ X *allMethodsExceptText }{X: &allMethodsExceptText{allMethods: allMethods{method: "UnmarshalNextJSON", value: []byte(`"hello"`)}}}), 6411 }, { 6412 name: name("Methods/OnlyMethodJSONv2"), 6413 inBuf: `{"X":"hello"}`, 6414 inVal: new(struct{ X *onlyMethodJSONv2 }), 6415 want: addr(struct{ X *onlyMethodJSONv2 }{X: &onlyMethodJSONv2{allMethods: allMethods{method: "UnmarshalNextJSON", value: []byte(`"hello"`)}}}), 6416 }, { 6417 name: name("Methods/OnlyMethodJSONv1"), 6418 inBuf: `{"X":"hello"}`, 6419 inVal: new(struct{ X *onlyMethodJSONv1 }), 6420 want: addr(struct{ X *onlyMethodJSONv1 }{X: &onlyMethodJSONv1{allMethods: allMethods{method: "UnmarshalJSON", value: []byte(`"hello"`)}}}), 6421 }, { 6422 name: name("Methods/OnlyMethodText"), 6423 inBuf: `{"X":"hello"}`, 6424 inVal: new(struct{ X *onlyMethodText }), 6425 want: addr(struct{ X *onlyMethodText }{X: &onlyMethodText{allMethods: allMethods{method: "UnmarshalText", value: []byte(`hello`)}}}), 6426 }, { 6427 name: name("Methods/IP"), 6428 inBuf: `"192.168.0.100"`, 6429 inVal: new(net.IP), 6430 want: addr(net.IPv4(192, 168, 0, 100)), 6431 }, { 6432 // NOTE: Fixes https://go.dev/issue/46516. 6433 name: name("Methods/Anonymous"), 6434 inBuf: `{"X":"hello"}`, 6435 inVal: new(struct{ X struct{ allMethods } }), 6436 want: addr(struct{ X struct{ allMethods } }{X: struct{ allMethods }{allMethods{method: "UnmarshalNextJSON", value: []byte(`"hello"`)}}}), 6437 }, { 6438 // NOTE: Fixes https://go.dev/issue/22967. 6439 name: name("Methods/Addressable"), 6440 inBuf: `{"V":"hello","M":{"K":"hello"},"I":"hello"}`, 6441 inVal: addr(struct { 6442 V allMethods 6443 M map[string]allMethods 6444 I any 6445 }{ 6446 I: allMethods{}, // need to initialize with concrete value 6447 }), 6448 want: addr(struct { 6449 V allMethods 6450 M map[string]allMethods 6451 I any 6452 }{ 6453 V: allMethods{method: "UnmarshalNextJSON", value: []byte(`"hello"`)}, 6454 M: map[string]allMethods{"K": {method: "UnmarshalNextJSON", value: []byte(`"hello"`)}}, 6455 I: allMethods{method: "UnmarshalNextJSON", value: []byte(`"hello"`)}, 6456 }), 6457 }, { 6458 // NOTE: Fixes https://go.dev/issue/29732. 6459 name: name("Methods/MapKey/JSONv2"), 6460 inBuf: `{"k1":"v1b","k2":"v2"}`, 6461 inVal: addr(map[structMethodJSONv2]string{{"k1"}: "v1a", {"k3"}: "v3"}), 6462 want: addr(map[structMethodJSONv2]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}), 6463 }, { 6464 // NOTE: Fixes https://go.dev/issue/29732. 6465 name: name("Methods/MapKey/JSONv1"), 6466 inBuf: `{"k1":"v1b","k2":"v2"}`, 6467 inVal: addr(map[structMethodJSONv1]string{{"k1"}: "v1a", {"k3"}: "v3"}), 6468 want: addr(map[structMethodJSONv1]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}), 6469 }, { 6470 name: name("Methods/MapKey/Text"), 6471 inBuf: `{"k1":"v1b","k2":"v2"}`, 6472 inVal: addr(map[structMethodText]string{{"k1"}: "v1a", {"k3"}: "v3"}), 6473 want: addr(map[structMethodText]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}), 6474 }, { 6475 name: name("Methods/Invalid/JSONv2/Error"), 6476 inBuf: `{}`, 6477 inVal: addr(unmarshalJSONv2Func(func(UnmarshalOptions, *Decoder) error { 6478 return errors.New("some error") 6479 })), 6480 wantErr: &SemanticError{action: "unmarshal", GoType: unmarshalJSONv2FuncType, Err: errors.New("some error")}, 6481 }, { 6482 name: name("Methods/Invalid/JSONv2/TooFew"), 6483 inVal: addr(unmarshalJSONv2Func(func(UnmarshalOptions, *Decoder) error { 6484 return nil // do nothing 6485 })), 6486 wantErr: &SemanticError{action: "unmarshal", GoType: unmarshalJSONv2FuncType, Err: errors.New("must read exactly one JSON value")}, 6487 }, { 6488 name: name("Methods/Invalid/JSONv2/TooMany"), 6489 inBuf: `{}{}`, 6490 inVal: addr(unmarshalJSONv2Func(func(uo UnmarshalOptions, dec *Decoder) error { 6491 dec.ReadValue() 6492 dec.ReadValue() 6493 return nil 6494 })), 6495 wantErr: &SemanticError{action: "unmarshal", GoType: unmarshalJSONv2FuncType, Err: errors.New("must read exactly one JSON value")}, 6496 }, { 6497 name: name("Methods/Invalid/JSONv2/SkipFunc"), 6498 inBuf: `{}`, 6499 inVal: addr(unmarshalJSONv2Func(func(UnmarshalOptions, *Decoder) error { 6500 return SkipFunc 6501 })), 6502 wantErr: &SemanticError{action: "unmarshal", GoType: unmarshalJSONv2FuncType, Err: errors.New("unmarshal method cannot be skipped")}, 6503 }, { 6504 name: name("Methods/Invalid/JSONv1/Error"), 6505 inBuf: `{}`, 6506 inVal: addr(unmarshalJSONv1Func(func([]byte) error { 6507 return errors.New("some error") 6508 })), 6509 wantErr: &SemanticError{action: "unmarshal", JSONKind: '{', GoType: unmarshalJSONv1FuncType, Err: errors.New("some error")}, 6510 }, { 6511 name: name("Methods/Invalid/JSONv1/SkipFunc"), 6512 inBuf: `{}`, 6513 inVal: addr(unmarshalJSONv1Func(func([]byte) error { 6514 return SkipFunc 6515 })), 6516 wantErr: &SemanticError{action: "unmarshal", JSONKind: '{', GoType: unmarshalJSONv1FuncType, Err: errors.New("unmarshal method cannot be skipped")}, 6517 }, { 6518 name: name("Methods/Invalid/Text/Error"), 6519 inBuf: `"value"`, 6520 inVal: addr(unmarshalTextFunc(func([]byte) error { 6521 return errors.New("some error") 6522 })), 6523 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: unmarshalTextFuncType, Err: errors.New("some error")}, 6524 }, { 6525 name: name("Methods/Invalid/Text/Syntax"), 6526 inBuf: `{}`, 6527 inVal: addr(unmarshalTextFunc(func([]byte) error { 6528 panic("should not be called") 6529 })), 6530 wantErr: &SemanticError{action: "unmarshal", JSONKind: '{', GoType: unmarshalTextFuncType, Err: errors.New("JSON value must be string type")}, 6531 }, { 6532 name: name("Methods/Invalid/Text/SkipFunc"), 6533 inBuf: `"value"`, 6534 inVal: addr(unmarshalTextFunc(func([]byte) error { 6535 return SkipFunc 6536 })), 6537 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: unmarshalTextFuncType, Err: errors.New("unmarshal method cannot be skipped")}, 6538 }, { 6539 name: name("Functions/String/V1"), 6540 uopts: UnmarshalOptions{ 6541 Unmarshalers: UnmarshalFuncV1(func(b []byte, v *string) error { 6542 if string(b) != `""` { 6543 return fmt.Errorf("got %s, want %s", b, `""`) 6544 } 6545 *v = "called" 6546 return nil 6547 }), 6548 }, 6549 inBuf: `""`, 6550 inVal: addr(""), 6551 want: addr("called"), 6552 }, { 6553 name: name("Functions/NamedString/V1/NoMatch"), 6554 uopts: UnmarshalOptions{ 6555 Unmarshalers: UnmarshalFuncV1(func(b []byte, v *namedString) error { 6556 panic("should not be called") 6557 }), 6558 }, 6559 inBuf: `""`, 6560 inVal: addr(""), 6561 want: addr(""), 6562 }, { 6563 name: name("Functions/NamedString/V1/Match"), 6564 uopts: UnmarshalOptions{ 6565 Unmarshalers: UnmarshalFuncV1(func(b []byte, v *namedString) error { 6566 if string(b) != `""` { 6567 return fmt.Errorf("got %s, want %s", b, `""`) 6568 } 6569 *v = "called" 6570 return nil 6571 }), 6572 }, 6573 inBuf: `""`, 6574 inVal: addr(namedString("")), 6575 want: addr(namedString("called")), 6576 }, { 6577 name: name("Functions/String/V2"), 6578 uopts: UnmarshalOptions{ 6579 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *string) error { 6580 switch b, err := dec.ReadValue(); { 6581 case err != nil: 6582 return err 6583 case string(b) != `""`: 6584 return fmt.Errorf("got %s, want %s", b, `""`) 6585 } 6586 *v = "called" 6587 return nil 6588 }), 6589 }, 6590 inBuf: `""`, 6591 inVal: addr(""), 6592 want: addr("called"), 6593 }, { 6594 name: name("Functions/NamedString/V2/NoMatch"), 6595 uopts: UnmarshalOptions{ 6596 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *namedString) error { 6597 panic("should not be called") 6598 }), 6599 }, 6600 inBuf: `""`, 6601 inVal: addr(""), 6602 want: addr(""), 6603 }, { 6604 name: name("Functions/NamedString/V2/Match"), 6605 uopts: UnmarshalOptions{ 6606 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *namedString) error { 6607 switch t, err := dec.ReadToken(); { 6608 case err != nil: 6609 return err 6610 case t.String() != ``: 6611 return fmt.Errorf("got %q, want %q", t, ``) 6612 } 6613 *v = "called" 6614 return nil 6615 }), 6616 }, 6617 inBuf: `""`, 6618 inVal: addr(namedString("")), 6619 want: addr(namedString("called")), 6620 }, { 6621 name: name("Functions/String/Empty1/NoMatch"), 6622 uopts: UnmarshalOptions{ 6623 Unmarshalers: new(Unmarshalers), 6624 }, 6625 inBuf: `""`, 6626 inVal: addr(""), 6627 want: addr(""), 6628 }, { 6629 name: name("Functions/String/Empty2/NoMatch"), 6630 uopts: UnmarshalOptions{ 6631 Unmarshalers: NewUnmarshalers(), 6632 }, 6633 inBuf: `""`, 6634 inVal: addr(""), 6635 want: addr(""), 6636 }, { 6637 name: name("Functions/String/V1/DirectError"), 6638 uopts: UnmarshalOptions{ 6639 Unmarshalers: UnmarshalFuncV1(func([]byte, *string) error { 6640 return errors.New("some error") 6641 }), 6642 }, 6643 inBuf: `""`, 6644 inVal: addr(""), 6645 want: addr(""), 6646 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: reflect.PointerTo(stringType), Err: errors.New("some error")}, 6647 }, { 6648 name: name("Functions/String/V1/SkipError"), 6649 uopts: UnmarshalOptions{ 6650 Unmarshalers: UnmarshalFuncV1(func([]byte, *string) error { 6651 return SkipFunc 6652 }), 6653 }, 6654 inBuf: `""`, 6655 inVal: addr(""), 6656 want: addr(""), 6657 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: reflect.PointerTo(stringType), Err: errors.New("unmarshal function of type func([]byte, T) error cannot be skipped")}, 6658 }, { 6659 name: name("Functions/String/V2/DirectError"), 6660 uopts: UnmarshalOptions{ 6661 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *string) error { 6662 return errors.New("some error") 6663 }), 6664 }, 6665 inBuf: `""`, 6666 inVal: addr(""), 6667 want: addr(""), 6668 wantErr: &SemanticError{action: "unmarshal", GoType: reflect.PointerTo(stringType), Err: errors.New("some error")}, 6669 }, { 6670 name: name("Functions/String/V2/TooFew"), 6671 uopts: UnmarshalOptions{ 6672 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *string) error { 6673 return nil 6674 }), 6675 }, 6676 inBuf: `""`, 6677 inVal: addr(""), 6678 want: addr(""), 6679 wantErr: &SemanticError{action: "unmarshal", GoType: reflect.PointerTo(stringType), Err: errors.New("must read exactly one JSON value")}, 6680 }, { 6681 name: name("Functions/String/V2/TooMany"), 6682 uopts: UnmarshalOptions{ 6683 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *string) error { 6684 if _, err := dec.ReadValue(); err != nil { 6685 return err 6686 } 6687 if _, err := dec.ReadValue(); err != nil { 6688 return err 6689 } 6690 return nil 6691 }), 6692 }, 6693 inBuf: `["",""]`, 6694 inVal: addr([]string{}), 6695 want: addr([]string{""}), 6696 wantErr: &SemanticError{action: "unmarshal", GoType: reflect.PointerTo(stringType), Err: errors.New("must read exactly one JSON value")}, 6697 }, { 6698 name: name("Functions/String/V2/Skipped"), 6699 uopts: UnmarshalOptions{ 6700 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *string) error { 6701 return SkipFunc 6702 }), 6703 }, 6704 inBuf: `""`, 6705 inVal: addr(""), 6706 want: addr(""), 6707 }, { 6708 name: name("Functions/String/V2/ProcessBeforeSkip"), 6709 uopts: UnmarshalOptions{ 6710 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *string) error { 6711 if _, err := dec.ReadValue(); err != nil { 6712 return err 6713 } 6714 return SkipFunc 6715 }), 6716 }, 6717 inBuf: `""`, 6718 inVal: addr(""), 6719 want: addr(""), 6720 wantErr: &SemanticError{action: "unmarshal", GoType: reflect.PointerTo(stringType), Err: errors.New("must not read any JSON tokens when skipping")}, 6721 }, { 6722 name: name("Functions/String/V2/WrappedSkipError"), 6723 uopts: UnmarshalOptions{ 6724 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *string) error { 6725 return fmt.Errorf("wrap: %w", SkipFunc) 6726 }), 6727 }, 6728 inBuf: `""`, 6729 inVal: addr(""), 6730 want: addr(""), 6731 wantErr: &SemanticError{action: "unmarshal", GoType: reflect.PointerTo(stringType), Err: fmt.Errorf("wrap: %w", SkipFunc)}, 6732 }, { 6733 name: name("Functions/Map/Key/NoCaseString/V1"), 6734 uopts: UnmarshalOptions{ 6735 Unmarshalers: UnmarshalFuncV1(func(b []byte, v *nocaseString) error { 6736 if string(b) != `"hello"` { 6737 return fmt.Errorf("got %s, want %s", b, `"hello"`) 6738 } 6739 *v = "called" 6740 return nil 6741 }), 6742 }, 6743 inBuf: `{"hello":"world"}`, 6744 inVal: addr(map[nocaseString]string{}), 6745 want: addr(map[nocaseString]string{"called": "world"}), 6746 }, { 6747 name: name("Functions/Map/Key/TextMarshaler/V1"), 6748 uopts: UnmarshalOptions{ 6749 Unmarshalers: UnmarshalFuncV1(func(b []byte, v encoding.TextMarshaler) error { 6750 if string(b) != `"hello"` { 6751 return fmt.Errorf("got %s, want %s", b, `"hello"`) 6752 } 6753 *v.(*nocaseString) = "called" 6754 return nil 6755 }), 6756 }, 6757 inBuf: `{"hello":"world"}`, 6758 inVal: addr(map[nocaseString]string{}), 6759 want: addr(map[nocaseString]string{"called": "world"}), 6760 }, { 6761 name: name("Functions/Map/Key/NoCaseString/V2"), 6762 uopts: UnmarshalOptions{ 6763 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *nocaseString) error { 6764 switch t, err := dec.ReadToken(); { 6765 case err != nil: 6766 return err 6767 case t.String() != "hello": 6768 return fmt.Errorf("got %q, want %q", t, "hello") 6769 } 6770 *v = "called" 6771 return nil 6772 }), 6773 }, 6774 inBuf: `{"hello":"world"}`, 6775 inVal: addr(map[nocaseString]string{}), 6776 want: addr(map[nocaseString]string{"called": "world"}), 6777 }, { 6778 name: name("Functions/Map/Key/TextMarshaler/V2"), 6779 uopts: UnmarshalOptions{ 6780 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v encoding.TextMarshaler) error { 6781 switch b, err := dec.ReadValue(); { 6782 case err != nil: 6783 return err 6784 case string(b) != `"hello"`: 6785 return fmt.Errorf("got %s, want %s", b, `"hello"`) 6786 } 6787 *v.(*nocaseString) = "called" 6788 return nil 6789 }), 6790 }, 6791 inBuf: `{"hello":"world"}`, 6792 inVal: addr(map[nocaseString]string{}), 6793 want: addr(map[nocaseString]string{"called": "world"}), 6794 }, { 6795 name: name("Functions/Map/Key/String/V1/DuplicateName"), 6796 uopts: UnmarshalOptions{ 6797 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *string) error { 6798 if _, err := dec.ReadValue(); err != nil { 6799 return err 6800 } 6801 *v = fmt.Sprintf("%d-%d", len(dec.tokens.stack), dec.tokens.last.length()) 6802 return nil 6803 }), 6804 }, 6805 inBuf: `{"name":"value","name":"value"}`, 6806 inVal: addr(map[string]string{}), 6807 want: addr(map[string]string{"1-1": "1-2"}), 6808 wantErr: &SemanticError{action: "unmarshal", GoType: reflect.PointerTo(stringType), Err: (&SyntacticError{str: `duplicate name "name" in object`}).withOffset(int64(len(`{"name":"value",`)))}, 6809 }, { 6810 name: name("Functions/Map/Value/NoCaseString/V1"), 6811 uopts: UnmarshalOptions{ 6812 Unmarshalers: UnmarshalFuncV1(func(b []byte, v *nocaseString) error { 6813 if string(b) != `"world"` { 6814 return fmt.Errorf("got %s, want %s", b, `"world"`) 6815 } 6816 *v = "called" 6817 return nil 6818 }), 6819 }, 6820 inBuf: `{"hello":"world"}`, 6821 inVal: addr(map[string]nocaseString{}), 6822 want: addr(map[string]nocaseString{"hello": "called"}), 6823 }, { 6824 name: name("Functions/Map/Value/TextMarshaler/V1"), 6825 uopts: UnmarshalOptions{ 6826 Unmarshalers: UnmarshalFuncV1(func(b []byte, v encoding.TextMarshaler) error { 6827 if string(b) != `"world"` { 6828 return fmt.Errorf("got %s, want %s", b, `"world"`) 6829 } 6830 *v.(*nocaseString) = "called" 6831 return nil 6832 }), 6833 }, 6834 inBuf: `{"hello":"world"}`, 6835 inVal: addr(map[string]nocaseString{}), 6836 want: addr(map[string]nocaseString{"hello": "called"}), 6837 }, { 6838 name: name("Functions/Map/Value/NoCaseString/V2"), 6839 uopts: UnmarshalOptions{ 6840 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *nocaseString) error { 6841 switch t, err := dec.ReadToken(); { 6842 case err != nil: 6843 return err 6844 case t.String() != "world": 6845 return fmt.Errorf("got %q, want %q", t, "world") 6846 } 6847 *v = "called" 6848 return nil 6849 }), 6850 }, 6851 inBuf: `{"hello":"world"}`, 6852 inVal: addr(map[string]nocaseString{}), 6853 want: addr(map[string]nocaseString{"hello": "called"}), 6854 }, { 6855 name: name("Functions/Map/Value/TextMarshaler/V2"), 6856 uopts: UnmarshalOptions{ 6857 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v encoding.TextMarshaler) error { 6858 switch b, err := dec.ReadValue(); { 6859 case err != nil: 6860 return err 6861 case string(b) != `"world"`: 6862 return fmt.Errorf("got %s, want %s", b, `"world"`) 6863 } 6864 *v.(*nocaseString) = "called" 6865 return nil 6866 }), 6867 }, 6868 inBuf: `{"hello":"world"}`, 6869 inVal: addr(map[string]nocaseString{}), 6870 want: addr(map[string]nocaseString{"hello": "called"}), 6871 }, { 6872 name: name("Funtions/Struct/Fields"), 6873 uopts: UnmarshalOptions{ 6874 Unmarshalers: NewUnmarshalers( 6875 UnmarshalFuncV1(func(b []byte, v *bool) error { 6876 if string(b) != `"called1"` { 6877 return fmt.Errorf("got %s, want %s", b, `"called1"`) 6878 } 6879 *v = true 6880 return nil 6881 }), 6882 UnmarshalFuncV1(func(b []byte, v *string) error { 6883 if string(b) != `"called2"` { 6884 return fmt.Errorf("got %s, want %s", b, `"called2"`) 6885 } 6886 *v = "called2" 6887 return nil 6888 }), 6889 UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *[]byte) error { 6890 switch t, err := dec.ReadToken(); { 6891 case err != nil: 6892 return err 6893 case t.String() != "called3": 6894 return fmt.Errorf("got %q, want %q", t, "called3") 6895 } 6896 *v = []byte("called3") 6897 return nil 6898 }), 6899 UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *int64) error { 6900 switch b, err := dec.ReadValue(); { 6901 case err != nil: 6902 return err 6903 case string(b) != `"called4"`: 6904 return fmt.Errorf("got %s, want %s", b, `"called4"`) 6905 } 6906 *v = 123 6907 return nil 6908 }), 6909 ), 6910 }, 6911 inBuf: `{"Bool":"called1","String":"called2","Bytes":"called3","Int":"called4","Uint":456,"Float":789}`, 6912 inVal: addr(structScalars{}), 6913 want: addr(structScalars{Bool: true, String: "called2", Bytes: []byte("called3"), Int: 123, Uint: 456, Float: 789}), 6914 }, { 6915 name: name("Functions/Struct/Inlined"), 6916 uopts: UnmarshalOptions{ 6917 Unmarshalers: NewUnmarshalers( 6918 UnmarshalFuncV1(func([]byte, *structInlinedL1) error { 6919 panic("should not be called") 6920 }), 6921 UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *StructEmbed2) error { 6922 panic("should not be called") 6923 }), 6924 ), 6925 }, 6926 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`, 6927 inVal: new(structInlined), 6928 want: addr(structInlined{ 6929 X: structInlinedL1{ 6930 X: &structInlinedL2{A: "A1", B: "B1" /* C: "C1" */}, 6931 StructEmbed1: StructEmbed1{ /* C: "C2" */ D: "D2" /* E: "E2" */}, 6932 }, 6933 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"}, 6934 }), 6935 }, { 6936 name: name("Functions/Slice/Elem"), 6937 uopts: UnmarshalOptions{ 6938 Unmarshalers: UnmarshalFuncV1(func(b []byte, v *string) error { 6939 *v = strings.Trim(strings.ToUpper(string(b)), `"`) 6940 return nil 6941 }), 6942 }, 6943 inBuf: `["hello","World"]`, 6944 inVal: addr([]string{}), 6945 want: addr([]string{"HELLO", "WORLD"}), 6946 }, { 6947 name: name("Functions/Array/Elem"), 6948 uopts: UnmarshalOptions{ 6949 Unmarshalers: UnmarshalFuncV1(func(b []byte, v *string) error { 6950 *v = strings.Trim(strings.ToUpper(string(b)), `"`) 6951 return nil 6952 }), 6953 }, 6954 inBuf: `["hello","World"]`, 6955 inVal: addr([2]string{}), 6956 want: addr([2]string{"HELLO", "WORLD"}), 6957 }, { 6958 name: name("Functions/Pointer/Nil"), 6959 uopts: UnmarshalOptions{ 6960 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *string) error { 6961 t, err := dec.ReadToken() 6962 *v = strings.ToUpper(t.String()) 6963 return err 6964 }), 6965 }, 6966 inBuf: `{"X":"hello"}`, 6967 inVal: addr(struct{ X *string }{nil}), 6968 want: addr(struct{ X *string }{addr("HELLO")}), 6969 }, { 6970 name: name("Functions/Pointer/NonNil"), 6971 uopts: UnmarshalOptions{ 6972 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *string) error { 6973 t, err := dec.ReadToken() 6974 *v = strings.ToUpper(t.String()) 6975 return err 6976 }), 6977 }, 6978 inBuf: `{"X":"hello"}`, 6979 inVal: addr(struct{ X *string }{addr("")}), 6980 want: addr(struct{ X *string }{addr("HELLO")}), 6981 }, { 6982 name: name("Functions/Interface/Nil"), 6983 uopts: UnmarshalOptions{ 6984 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v fmt.Stringer) error { 6985 panic("should not be called") 6986 }), 6987 }, 6988 inBuf: `{"X":"hello"}`, 6989 inVal: addr(struct{ X fmt.Stringer }{nil}), 6990 want: addr(struct{ X fmt.Stringer }{nil}), 6991 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: fmtStringerType, Err: errors.New("cannot derive concrete type for non-empty interface")}, 6992 }, { 6993 name: name("Functions/Interface/NetIP"), 6994 uopts: UnmarshalOptions{ 6995 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *fmt.Stringer) error { 6996 *v = net.IP{} 6997 return SkipFunc 6998 }), 6999 }, 7000 inBuf: `{"X":"1.1.1.1"}`, 7001 inVal: addr(struct{ X fmt.Stringer }{nil}), 7002 want: addr(struct{ X fmt.Stringer }{net.IPv4(1, 1, 1, 1)}), 7003 }, { 7004 name: name("Functions/Interface/NewPointerNetIP"), 7005 uopts: UnmarshalOptions{ 7006 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *fmt.Stringer) error { 7007 *v = new(net.IP) 7008 return SkipFunc 7009 }), 7010 }, 7011 inBuf: `{"X":"1.1.1.1"}`, 7012 inVal: addr(struct{ X fmt.Stringer }{nil}), 7013 want: addr(struct{ X fmt.Stringer }{addr(net.IPv4(1, 1, 1, 1))}), 7014 }, { 7015 name: name("Functions/Interface/NilPointerNetIP"), 7016 uopts: UnmarshalOptions{ 7017 Unmarshalers: UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *fmt.Stringer) error { 7018 *v = (*net.IP)(nil) 7019 return SkipFunc 7020 }), 7021 }, 7022 inBuf: `{"X":"1.1.1.1"}`, 7023 inVal: addr(struct{ X fmt.Stringer }{nil}), 7024 want: addr(struct{ X fmt.Stringer }{addr(net.IPv4(1, 1, 1, 1))}), 7025 }, { 7026 name: name("Functions/Interface/NilPointerNetIP/Override"), 7027 uopts: UnmarshalOptions{ 7028 Unmarshalers: NewUnmarshalers( 7029 UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *fmt.Stringer) error { 7030 *v = (*net.IP)(nil) 7031 return SkipFunc 7032 }), 7033 UnmarshalFuncV1(func(b []byte, v *net.IP) error { 7034 b = bytes.ReplaceAll(b, []byte(`1`), []byte(`8`)) 7035 return v.UnmarshalText(bytes.Trim(b, `"`)) 7036 }), 7037 ), 7038 }, 7039 inBuf: `{"X":"1.1.1.1"}`, 7040 inVal: addr(struct{ X fmt.Stringer }{nil}), 7041 want: addr(struct{ X fmt.Stringer }{addr(net.IPv4(8, 8, 8, 8))}), 7042 }, { 7043 name: name("Functions/Interface/Any"), 7044 inBuf: `[null,{},{},{},{},{},{},{},{},{},{},{},{},"LAST"]`, 7045 inVal: addr([...]any{ 7046 nil, // nil 7047 valueStringer{}, // T 7048 (*valueStringer)(nil), // *T 7049 addr(valueStringer{}), // *T 7050 (**valueStringer)(nil), // **T 7051 addr((*valueStringer)(nil)), // **T 7052 addr(addr(valueStringer{})), // **T 7053 pointerStringer{}, // T 7054 (*pointerStringer)(nil), // *T 7055 addr(pointerStringer{}), // *T 7056 (**pointerStringer)(nil), // **T 7057 addr((*pointerStringer)(nil)), // **T 7058 addr(addr(pointerStringer{})), // **T 7059 "LAST", 7060 }), 7061 uopts: UnmarshalOptions{ 7062 Unmarshalers: func() *Unmarshalers { 7063 type P [2]int 7064 type PV struct { 7065 P P 7066 V any 7067 } 7068 7069 var lastChecks []func() error 7070 checkLast := func() error { 7071 for _, fn := range lastChecks { 7072 if err := fn(); err != nil { 7073 return err 7074 } 7075 } 7076 return SkipFunc 7077 } 7078 makeValueChecker := func(name string, want []PV) func(d *Decoder, v any) error { 7079 checkNext := func(d *Decoder, v any) error { 7080 p := P{len(d.tokens.stack), d.tokens.last.length()} 7081 rv := reflect.ValueOf(v) 7082 pv := PV{p, v} 7083 switch { 7084 case len(want) == 0: 7085 return fmt.Errorf("%s: %v: got more values than expected", name, p) 7086 case !rv.IsValid() || rv.Kind() != reflect.Pointer || rv.IsNil(): 7087 return fmt.Errorf("%s: %v: got %#v, want non-nil pointer type", name, p, v) 7088 case !reflect.DeepEqual(pv, want[0]): 7089 return fmt.Errorf("%s:\n\tgot %#v\n\twant %#v", name, pv, want[0]) 7090 default: 7091 want = want[1:] 7092 return SkipFunc 7093 } 7094 } 7095 lastChecks = append(lastChecks, func() error { 7096 if len(want) > 0 { 7097 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want)) 7098 } 7099 return nil 7100 }) 7101 return checkNext 7102 } 7103 makePositionChecker := func(name string, want []P) func(d *Decoder, v any) error { 7104 checkNext := func(d *Decoder, v any) error { 7105 p := P{len(d.tokens.stack), d.tokens.last.length()} 7106 switch { 7107 case len(want) == 0: 7108 return fmt.Errorf("%s: %v: got more values than wanted", name, p) 7109 case p != want[0]: 7110 return fmt.Errorf("%s: got %v, want %v", name, p, want[0]) 7111 default: 7112 want = want[1:] 7113 return SkipFunc 7114 } 7115 } 7116 lastChecks = append(lastChecks, func() error { 7117 if len(want) > 0 { 7118 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want)) 7119 } 7120 return nil 7121 }) 7122 return checkNext 7123 } 7124 7125 // In contrast to marshal, unmarshal automatically allocates for 7126 // nil pointers, which causes unmarshal to visit more values. 7127 wantAny := []PV{ 7128 {P{1, 0}, addr(any(nil))}, 7129 {P{1, 1}, addr(any(valueStringer{}))}, 7130 {P{1, 1}, addr(valueStringer{})}, 7131 {P{1, 2}, addr(any((*valueStringer)(nil)))}, 7132 {P{1, 2}, addr((*valueStringer)(nil))}, 7133 {P{1, 2}, addr(valueStringer{})}, 7134 {P{1, 3}, addr(any(addr(valueStringer{})))}, 7135 {P{1, 3}, addr(addr(valueStringer{}))}, 7136 {P{1, 3}, addr(valueStringer{})}, 7137 {P{1, 4}, addr(any((**valueStringer)(nil)))}, 7138 {P{1, 4}, addr((**valueStringer)(nil))}, 7139 {P{1, 4}, addr((*valueStringer)(nil))}, 7140 {P{1, 4}, addr(valueStringer{})}, 7141 {P{1, 5}, addr(any(addr((*valueStringer)(nil))))}, 7142 {P{1, 5}, addr(addr((*valueStringer)(nil)))}, 7143 {P{1, 5}, addr((*valueStringer)(nil))}, 7144 {P{1, 5}, addr(valueStringer{})}, 7145 {P{1, 6}, addr(any(addr(addr(valueStringer{}))))}, 7146 {P{1, 6}, addr(addr(addr(valueStringer{})))}, 7147 {P{1, 6}, addr(addr(valueStringer{}))}, 7148 {P{1, 6}, addr(valueStringer{})}, 7149 {P{1, 7}, addr(any(pointerStringer{}))}, 7150 {P{1, 7}, addr(pointerStringer{})}, 7151 {P{1, 8}, addr(any((*pointerStringer)(nil)))}, 7152 {P{1, 8}, addr((*pointerStringer)(nil))}, 7153 {P{1, 8}, addr(pointerStringer{})}, 7154 {P{1, 9}, addr(any(addr(pointerStringer{})))}, 7155 {P{1, 9}, addr(addr(pointerStringer{}))}, 7156 {P{1, 9}, addr(pointerStringer{})}, 7157 {P{1, 10}, addr(any((**pointerStringer)(nil)))}, 7158 {P{1, 10}, addr((**pointerStringer)(nil))}, 7159 {P{1, 10}, addr((*pointerStringer)(nil))}, 7160 {P{1, 10}, addr(pointerStringer{})}, 7161 {P{1, 11}, addr(any(addr((*pointerStringer)(nil))))}, 7162 {P{1, 11}, addr(addr((*pointerStringer)(nil)))}, 7163 {P{1, 11}, addr((*pointerStringer)(nil))}, 7164 {P{1, 11}, addr(pointerStringer{})}, 7165 {P{1, 12}, addr(any(addr(addr(pointerStringer{}))))}, 7166 {P{1, 12}, addr(addr(addr(pointerStringer{})))}, 7167 {P{1, 12}, addr(addr(pointerStringer{}))}, 7168 {P{1, 12}, addr(pointerStringer{})}, 7169 {P{1, 13}, addr(any("LAST"))}, 7170 {P{1, 13}, addr("LAST")}, 7171 } 7172 checkAny := makeValueChecker("any", wantAny) 7173 anyUnmarshaler := UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v any) error { 7174 return checkAny(dec, v) 7175 }) 7176 7177 var wantPointerAny []PV 7178 for _, v := range wantAny { 7179 if _, ok := v.V.(*any); ok { 7180 wantPointerAny = append(wantPointerAny, v) 7181 } 7182 } 7183 checkPointerAny := makeValueChecker("*any", wantPointerAny) 7184 pointerAnyUnmarshaler := UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *any) error { 7185 return checkPointerAny(dec, v) 7186 }) 7187 7188 checkNamedAny := makeValueChecker("namedAny", wantAny) 7189 namedAnyUnmarshaler := UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v namedAny) error { 7190 return checkNamedAny(dec, v) 7191 }) 7192 7193 checkPointerNamedAny := makeValueChecker("*namedAny", nil) 7194 pointerNamedAnyUnmarshaler := UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *namedAny) error { 7195 return checkPointerNamedAny(dec, v) 7196 }) 7197 7198 type stringer = fmt.Stringer 7199 var wantStringer []PV 7200 for _, v := range wantAny { 7201 if _, ok := v.V.(stringer); ok { 7202 wantStringer = append(wantStringer, v) 7203 } 7204 } 7205 checkStringer := makeValueChecker("stringer", wantStringer) 7206 stringerUnmarshaler := UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v stringer) error { 7207 return checkStringer(dec, v) 7208 }) 7209 7210 checkPointerStringer := makeValueChecker("*stringer", nil) 7211 pointerStringerUnmarshaler := UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *stringer) error { 7212 return checkPointerStringer(dec, v) 7213 }) 7214 7215 wantValueStringer := []P{{1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}} 7216 checkPointerValueStringer := makePositionChecker("*valueStringer", wantValueStringer) 7217 pointerValueStringerUnmarshaler := UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *valueStringer) error { 7218 return checkPointerValueStringer(dec, v) 7219 }) 7220 7221 wantPointerStringer := []P{{1, 7}, {1, 8}, {1, 9}, {1, 10}, {1, 11}, {1, 12}} 7222 checkPointerPointerStringer := makePositionChecker("*pointerStringer", wantPointerStringer) 7223 pointerPointerStringerUnmarshaler := UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *pointerStringer) error { 7224 return checkPointerPointerStringer(dec, v) 7225 }) 7226 7227 lastUnmarshaler := UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *string) error { 7228 return checkLast() 7229 }) 7230 7231 return NewUnmarshalers( 7232 // This is just like unmarshaling into a Go array, 7233 // but avoids zeroing the element before calling unmarshal. 7234 UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *[14]any) error { 7235 if _, err := dec.ReadToken(); err != nil { 7236 return err 7237 } 7238 for i := 0; i < len(*v); i++ { 7239 if err := uo.UnmarshalNext(dec, &(*v)[i]); err != nil { 7240 return err 7241 } 7242 } 7243 if _, err := dec.ReadToken(); err != nil { 7244 return err 7245 } 7246 return nil 7247 }), 7248 7249 anyUnmarshaler, 7250 pointerAnyUnmarshaler, 7251 namedAnyUnmarshaler, 7252 pointerNamedAnyUnmarshaler, // never called 7253 stringerUnmarshaler, 7254 pointerStringerUnmarshaler, // never called 7255 pointerValueStringerUnmarshaler, 7256 pointerPointerStringerUnmarshaler, 7257 lastUnmarshaler, 7258 ) 7259 }(), 7260 }, 7261 }, { 7262 name: name("Functions/Precedence/V1First"), 7263 uopts: UnmarshalOptions{ 7264 Unmarshalers: NewUnmarshalers( 7265 UnmarshalFuncV1(func(b []byte, v *string) error { 7266 if string(b) != `"called"` { 7267 return fmt.Errorf("got %s, want %s", b, `"called"`) 7268 } 7269 *v = "called" 7270 return nil 7271 }), 7272 UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *string) error { 7273 panic("should not be called") 7274 }), 7275 ), 7276 }, 7277 inBuf: `"called"`, 7278 inVal: addr(""), 7279 want: addr("called"), 7280 }, { 7281 name: name("Functions/Precedence/V2First"), 7282 uopts: UnmarshalOptions{ 7283 Unmarshalers: NewUnmarshalers( 7284 UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *string) error { 7285 switch t, err := dec.ReadToken(); { 7286 case err != nil: 7287 return err 7288 case t.String() != "called": 7289 return fmt.Errorf("got %q, want %q", t, "called") 7290 } 7291 *v = "called" 7292 return nil 7293 }), 7294 UnmarshalFuncV1(func([]byte, *string) error { 7295 panic("should not be called") 7296 }), 7297 ), 7298 }, 7299 inBuf: `"called"`, 7300 inVal: addr(""), 7301 want: addr("called"), 7302 }, { 7303 name: name("Functions/Precedence/V2Skipped"), 7304 uopts: UnmarshalOptions{ 7305 Unmarshalers: NewUnmarshalers( 7306 UnmarshalFuncV2(func(uo UnmarshalOptions, dec *Decoder, v *string) error { 7307 return SkipFunc 7308 }), 7309 UnmarshalFuncV1(func(b []byte, v *string) error { 7310 if string(b) != `"called"` { 7311 return fmt.Errorf("got %s, want %s", b, `"called"`) 7312 } 7313 *v = "called" 7314 return nil 7315 }), 7316 ), 7317 }, 7318 inBuf: `"called"`, 7319 inVal: addr(""), 7320 want: addr("called"), 7321 }, { 7322 name: name("Functions/Precedence/NestedFirst"), 7323 uopts: UnmarshalOptions{ 7324 Unmarshalers: NewUnmarshalers( 7325 NewUnmarshalers( 7326 UnmarshalFuncV1(func(b []byte, v *string) error { 7327 if string(b) != `"called"` { 7328 return fmt.Errorf("got %s, want %s", b, `"called"`) 7329 } 7330 *v = "called" 7331 return nil 7332 }), 7333 ), 7334 UnmarshalFuncV1(func([]byte, *string) error { 7335 panic("should not be called") 7336 }), 7337 ), 7338 }, 7339 inBuf: `"called"`, 7340 inVal: addr(""), 7341 want: addr("called"), 7342 }, { 7343 name: name("Functions/Precedence/NestedLast"), 7344 uopts: UnmarshalOptions{ 7345 Unmarshalers: NewUnmarshalers( 7346 UnmarshalFuncV1(func(b []byte, v *string) error { 7347 if string(b) != `"called"` { 7348 return fmt.Errorf("got %s, want %s", b, `"called"`) 7349 } 7350 *v = "called" 7351 return nil 7352 }), 7353 NewUnmarshalers( 7354 UnmarshalFuncV1(func([]byte, *string) error { 7355 panic("should not be called") 7356 }), 7357 ), 7358 ), 7359 }, 7360 inBuf: `"called"`, 7361 inVal: addr(""), 7362 want: addr("called"), 7363 }, { 7364 name: name("Duration/Null"), 7365 inBuf: `{"D1":null,"D2":null}`, 7366 inVal: addr(struct { 7367 D1 time.Duration 7368 D2 time.Duration `json:",format:nanos"` 7369 }{1, 1}), 7370 want: addr(struct { 7371 D1 time.Duration 7372 D2 time.Duration `json:",format:nanos"` 7373 }{0, 0}), 7374 }, { 7375 name: name("Duration/Zero"), 7376 inBuf: `{"D1":"0s","D2":0}`, 7377 inVal: addr(struct { 7378 D1 time.Duration 7379 D2 time.Duration `json:",format:nanos"` 7380 }{1, 1}), 7381 want: addr(struct { 7382 D1 time.Duration 7383 D2 time.Duration `json:",format:nanos"` 7384 }{0, 0}), 7385 }, { 7386 name: name("Duration/Positive"), 7387 inBuf: `{"D1":"34293h33m9.123456789s","D2":123456789123456789}`, 7388 inVal: new(struct { 7389 D1 time.Duration 7390 D2 time.Duration `json:",format:nanos"` 7391 }), 7392 want: addr(struct { 7393 D1 time.Duration 7394 D2 time.Duration `json:",format:nanos"` 7395 }{ 7396 123456789123456789, 7397 123456789123456789, 7398 }), 7399 }, { 7400 name: name("Duration/Negative"), 7401 inBuf: `{"D1":"-34293h33m9.123456789s","D2":-123456789123456789}`, 7402 inVal: new(struct { 7403 D1 time.Duration 7404 D2 time.Duration `json:",format:nanos"` 7405 }), 7406 want: addr(struct { 7407 D1 time.Duration 7408 D2 time.Duration `json:",format:nanos"` 7409 }{ 7410 -123456789123456789, 7411 -123456789123456789, 7412 }), 7413 }, { 7414 name: name("Duration/Nanos/String"), 7415 inBuf: `{"D":"12345"}`, 7416 inVal: addr(struct { 7417 D time.Duration `json:",string,format:nanos"` 7418 }{1}), 7419 want: addr(struct { 7420 D time.Duration `json:",string,format:nanos"` 7421 }{12345}), 7422 }, { 7423 name: name("Duration/Nanos/String/Invalid"), 7424 inBuf: `{"D":"+12345"}`, 7425 inVal: addr(struct { 7426 D time.Duration `json:",string,format:nanos"` 7427 }{1}), 7428 want: addr(struct { 7429 D time.Duration `json:",string,format:nanos"` 7430 }{1}), 7431 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: timeDurationType, Err: fmt.Errorf(`cannot parse "+12345" as signed integer: %w`, strconv.ErrSyntax)}, 7432 }, { 7433 name: name("Duration/Nanos/Mismatch"), 7434 inBuf: `{"D":"34293h33m9.123456789s"}`, 7435 inVal: addr(struct { 7436 D time.Duration `json:",format:nanos"` 7437 }{1}), 7438 want: addr(struct { 7439 D time.Duration `json:",format:nanos"` 7440 }{1}), 7441 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: timeDurationType}, 7442 }, { 7443 name: name("Duration/Nanos/Invalid"), 7444 inBuf: `{"D":1.324}`, 7445 inVal: addr(struct { 7446 D time.Duration `json:",format:nanos"` 7447 }{1}), 7448 want: addr(struct { 7449 D time.Duration `json:",format:nanos"` 7450 }{1}), 7451 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: timeDurationType, Err: fmt.Errorf(`cannot parse "1.324" as signed integer: %w`, strconv.ErrSyntax)}, 7452 }, { 7453 name: name("Duration/String/Mismatch"), 7454 inBuf: `{"D":-123456789123456789}`, 7455 inVal: addr(struct { 7456 D time.Duration 7457 }{1}), 7458 want: addr(struct { 7459 D time.Duration 7460 }{1}), 7461 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: timeDurationType}, 7462 }, { 7463 name: name("Duration/String/Invalid"), 7464 inBuf: `{"D":"5minkutes"}`, 7465 inVal: addr(struct { 7466 D time.Duration 7467 }{1}), 7468 want: addr(struct { 7469 D time.Duration 7470 }{1}), 7471 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: timeDurationType, Err: func() error { 7472 _, err := time.ParseDuration("5minkutes") 7473 return err 7474 }()}, 7475 }, { 7476 name: name("Duration/Syntax/Invalid"), 7477 inBuf: `{"D":x}`, 7478 inVal: addr(struct { 7479 D time.Duration 7480 }{1}), 7481 want: addr(struct { 7482 D time.Duration 7483 }{1}), 7484 wantErr: newInvalidCharacterError([]byte("x"), "at start of value").withOffset(int64(len(`{"D":`))), 7485 }, { 7486 name: name("Duration/Format/Invalid"), 7487 inBuf: `{"D":"0s"}`, 7488 inVal: addr(struct { 7489 D time.Duration `json:",format:invalid"` 7490 }{1}), 7491 want: addr(struct { 7492 D time.Duration `json:",format:invalid"` 7493 }{1}), 7494 wantErr: &SemanticError{action: "unmarshal", GoType: timeDurationType, Err: errors.New(`invalid format flag: "invalid"`)}, 7495 }, { 7496 name: name("Duration/IgnoreInvalidFormat"), 7497 uopts: UnmarshalOptions{formatDepth: 1000, format: "invalid"}, 7498 inBuf: `"1s"`, 7499 inVal: addr(time.Duration(0)), 7500 want: addr(time.Second), 7501 }, { 7502 name: name("Time/Zero"), 7503 inBuf: `{"T1":"0001-01-01T00:00:00Z","T2":"01 Jan 01 00:00 UTC","T3":"0001-01-01","T4":"0001-01-01T00:00:00Z","T5":"0001-01-01T00:00:00Z"}`, 7504 inVal: new(struct { 7505 T1 time.Time 7506 T2 time.Time `json:",format:RFC822"` 7507 T3 time.Time `json:",format:'2006-01-02'"` 7508 T4 time.Time `json:",omitzero"` 7509 T5 time.Time `json:",omitempty"` 7510 }), 7511 want: addr(struct { 7512 T1 time.Time 7513 T2 time.Time `json:",format:RFC822"` 7514 T3 time.Time `json:",format:'2006-01-02'"` 7515 T4 time.Time `json:",omitzero"` 7516 T5 time.Time `json:",omitempty"` 7517 }{ 7518 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"), 7519 mustParseTime(time.RFC822, "01 Jan 01 00:00 UTC"), 7520 mustParseTime("2006-01-02", "0001-01-01"), 7521 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"), 7522 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"), 7523 }), 7524 }, { 7525 name: name("Time/Format"), 7526 inBuf: `{ 7527 "T1": "1234-01-02T03:04:05.000000006Z", 7528 "T2": "Mon Jan 2 03:04:05 1234", 7529 "T3": "Mon Jan 2 03:04:05 UTC 1234", 7530 "T4": "Mon Jan 02 03:04:05 +0000 1234", 7531 "T5": "02 Jan 34 03:04 UTC", 7532 "T6": "02 Jan 34 03:04 +0000", 7533 "T7": "Monday, 02-Jan-34 03:04:05 UTC", 7534 "T8": "Mon, 02 Jan 1234 03:04:05 UTC", 7535 "T9": "Mon, 02 Jan 1234 03:04:05 +0000", 7536 "T10": "1234-01-02T03:04:05Z", 7537 "T11": "1234-01-02T03:04:05.000000006Z", 7538 "T12": "3:04AM", 7539 "T13": "Jan 2 03:04:05", 7540 "T14": "Jan 2 03:04:05.000", 7541 "T15": "Jan 2 03:04:05.000000", 7542 "T16": "Jan 2 03:04:05.000000006", 7543 "T17": "1234-01-02", 7544 "T18": "\"weird\"1234" 7545 }`, 7546 inVal: new(structTimeFormat), 7547 want: addr(structTimeFormat{ 7548 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"), 7549 mustParseTime(time.ANSIC, "Mon Jan 2 03:04:05 1234"), 7550 mustParseTime(time.UnixDate, "Mon Jan 2 03:04:05 UTC 1234"), 7551 mustParseTime(time.RubyDate, "Mon Jan 02 03:04:05 +0000 1234"), 7552 mustParseTime(time.RFC822, "02 Jan 34 03:04 UTC"), 7553 mustParseTime(time.RFC822Z, "02 Jan 34 03:04 +0000"), 7554 mustParseTime(time.RFC850, "Monday, 02-Jan-34 03:04:05 UTC"), 7555 mustParseTime(time.RFC1123, "Mon, 02 Jan 1234 03:04:05 UTC"), 7556 mustParseTime(time.RFC1123Z, "Mon, 02 Jan 1234 03:04:05 +0000"), 7557 mustParseTime(time.RFC3339, "1234-01-02T03:04:05Z"), 7558 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"), 7559 mustParseTime(time.Kitchen, "3:04AM"), 7560 mustParseTime(time.Stamp, "Jan 2 03:04:05"), 7561 mustParseTime(time.StampMilli, "Jan 2 03:04:05.000"), 7562 mustParseTime(time.StampMicro, "Jan 2 03:04:05.000000"), 7563 mustParseTime(time.StampNano, "Jan 2 03:04:05.000000006"), 7564 mustParseTime("2006-01-02", "1234-01-02"), 7565 mustParseTime(`\"weird\"2006`, `\"weird\"1234`), 7566 }), 7567 }, { 7568 name: name("Time/Format/Null"), 7569 inBuf: `{"T1": null,"T2": null,"T3": null,"T4": null,"T5": null,"T6": null,"T7": null,"T8": null,"T9": null,"T10": null,"T11": null,"T12": null,"T13": null,"T14": null,"T15": null,"T16": null,"T17": null,"T18": null}`, 7570 inVal: addr(structTimeFormat{ 7571 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"), 7572 mustParseTime(time.ANSIC, "Mon Jan 2 03:04:05 1234"), 7573 mustParseTime(time.UnixDate, "Mon Jan 2 03:04:05 UTC 1234"), 7574 mustParseTime(time.RubyDate, "Mon Jan 02 03:04:05 +0000 1234"), 7575 mustParseTime(time.RFC822, "02 Jan 34 03:04 UTC"), 7576 mustParseTime(time.RFC822Z, "02 Jan 34 03:04 +0000"), 7577 mustParseTime(time.RFC850, "Monday, 02-Jan-34 03:04:05 UTC"), 7578 mustParseTime(time.RFC1123, "Mon, 02 Jan 1234 03:04:05 UTC"), 7579 mustParseTime(time.RFC1123Z, "Mon, 02 Jan 1234 03:04:05 +0000"), 7580 mustParseTime(time.RFC3339, "1234-01-02T03:04:05Z"), 7581 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"), 7582 mustParseTime(time.Kitchen, "3:04AM"), 7583 mustParseTime(time.Stamp, "Jan 2 03:04:05"), 7584 mustParseTime(time.StampMilli, "Jan 2 03:04:05.000"), 7585 mustParseTime(time.StampMicro, "Jan 2 03:04:05.000000"), 7586 mustParseTime(time.StampNano, "Jan 2 03:04:05.000000006"), 7587 mustParseTime("2006-01-02", "1234-01-02"), 7588 mustParseTime(`\"weird\"2006`, `\"weird\"1234`), 7589 }), 7590 want: new(structTimeFormat), 7591 }, { 7592 name: name("Time/RFC3339/Mismatch"), 7593 inBuf: `{"T":1234}`, 7594 inVal: new(struct { 7595 T time.Time 7596 }), 7597 wantErr: &SemanticError{action: "unmarshal", JSONKind: '0', GoType: timeTimeType}, 7598 }, { 7599 name: name("Time/RFC3339/ParseError"), 7600 inBuf: `{"T":"2021-09-29T12:44:52"}`, 7601 inVal: new(struct { 7602 T time.Time 7603 }), 7604 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: timeTimeType, Err: func() error { 7605 _, err := time.Parse(time.RFC3339, "2021-09-29T12:44:52") 7606 return err 7607 }()}, 7608 }, { 7609 name: name("Time/Format/Invalid"), 7610 inBuf: `{"T":""}`, 7611 inVal: new(struct { 7612 T time.Time `json:",format:UndefinedConstant"` 7613 }), 7614 wantErr: &SemanticError{action: "unmarshal", GoType: timeTimeType, Err: errors.New(`undefined format layout: UndefinedConstant`)}, 7615 }, { 7616 name: name("Time/Format/SingleDigitHour"), 7617 inBuf: `{"T":"2000-01-01T1:12:34Z"}`, 7618 inVal: new(struct{ T time.Time }), 7619 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: timeTimeType, Err: &time.ParseError{time.RFC3339, "2000-01-01T1:12:34Z", "15", "1", ""}}, 7620 }, { 7621 name: name("Time/Format/SubsecondComma"), 7622 inBuf: `{"T":"2000-01-01T00:00:00,000Z"}`, 7623 inVal: new(struct{ T time.Time }), 7624 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: timeTimeType, Err: &time.ParseError{time.RFC3339, "2000-01-01T00:00:00,000Z", ".", ",", ""}}, 7625 }, { 7626 name: name("Time/Format/TimezoneHourOverflow"), 7627 inBuf: `{"T":"2000-01-01T00:00:00+24:00"}`, 7628 inVal: new(struct{ T time.Time }), 7629 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: timeTimeType, Err: &time.ParseError{time.RFC3339, "2000-01-01T00:00:00+24:00", "Z07:00", "+24:00", ": timezone hour out of range"}}, 7630 }, { 7631 name: name("Time/Format/TimezoneMinuteOverflow"), 7632 inBuf: `{"T":"2000-01-01T00:00:00+00:60"}`, 7633 inVal: new(struct{ T time.Time }), 7634 wantErr: &SemanticError{action: "unmarshal", JSONKind: '"', GoType: timeTimeType, Err: &time.ParseError{time.RFC3339, "2000-01-01T00:00:00+00:60", "Z07:00", "+00:60", ": timezone minute out of range"}}, 7635 }, { 7636 name: name("Time/Syntax/Invalid"), 7637 inBuf: `{"T":x}`, 7638 inVal: new(struct { 7639 T time.Time 7640 }), 7641 wantErr: newInvalidCharacterError([]byte("x"), "at start of value").withOffset(int64(len(`{"D":`))), 7642 }, { 7643 name: name("Time/IgnoreInvalidFormat"), 7644 uopts: UnmarshalOptions{formatDepth: 1000, format: "invalid"}, 7645 inBuf: `"2000-01-01T00:00:00Z"`, 7646 inVal: addr(time.Time{}), 7647 want: addr(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)), 7648 }} 7649 7650 for _, tt := range tests { 7651 t.Run(tt.name.name, func(t *testing.T) { 7652 got := tt.inVal 7653 gotErr := tt.uopts.Unmarshal(tt.dopts, []byte(tt.inBuf), got) 7654 if !reflect.DeepEqual(got, tt.want) && tt.want != nil { 7655 t.Errorf("%s: Unmarshal output mismatch:\ngot %v\nwant %v", tt.name.where, got, tt.want) 7656 } 7657 if !reflect.DeepEqual(gotErr, tt.wantErr) { 7658 t.Errorf("%s: Unmarshal error mismatch:\ngot %v\nwant %v", tt.name.where, gotErr, tt.wantErr) 7659 } 7660 }) 7661 } 7662 } 7663 7664 func TestMarshalInvalidNamespace(t *testing.T) { 7665 tests := []struct { 7666 name testName 7667 val any 7668 }{ 7669 {name("Map"), map[string]string{"X": "\xde\xad\xbe\xef"}}, 7670 {name("Struct"), struct{ X string }{"\xde\xad\xbe\xef"}}, 7671 } 7672 for _, tt := range tests { 7673 t.Run(tt.name.name, func(t *testing.T) { 7674 enc := NewEncoder(new(bytes.Buffer)) 7675 if err := (MarshalOptions{}).MarshalNext(enc, tt.val); err == nil { 7676 t.Fatalf("%s: MarshalNext error is nil, want non-nil", tt.name.where) 7677 } 7678 for _, tok := range []Token{Null, String(""), Int(0), ObjectStart, ObjectEnd, ArrayStart, ArrayEnd} { 7679 if err := enc.WriteToken(tok); err == nil { 7680 t.Fatalf("%s: WriteToken error is nil, want non-nil", tt.name.where) 7681 } 7682 } 7683 for _, val := range []string{`null`, `""`, `0`, `{}`, `[]`} { 7684 if err := enc.WriteValue([]byte(val)); err == nil { 7685 t.Fatalf("%s: WriteToken error is nil, want non-nil", tt.name.where) 7686 } 7687 } 7688 }) 7689 } 7690 } 7691 7692 func TestUnmarshalInvalidNamespace(t *testing.T) { 7693 tests := []struct { 7694 name testName 7695 val any 7696 }{ 7697 {name("Map"), addr(map[string]int{})}, 7698 {name("Struct"), addr(struct{ X int }{})}, 7699 } 7700 for _, tt := range tests { 7701 t.Run(tt.name.name, func(t *testing.T) { 7702 dec := NewDecoder(strings.NewReader(`{"X":""}`)) 7703 if err := (UnmarshalOptions{}).UnmarshalNext(dec, tt.val); err == nil { 7704 t.Fatalf("%s: UnmarshalNext error is nil, want non-nil", tt.name.where) 7705 } 7706 if _, err := dec.ReadToken(); err == nil { 7707 t.Fatalf("%s: ReadToken error is nil, want non-nil", tt.name.where) 7708 } 7709 if _, err := dec.ReadValue(); err == nil { 7710 t.Fatalf("%s: ReadValue error is nil, want non-nil", tt.name.where) 7711 } 7712 }) 7713 } 7714 } 7715 7716 func TestUnmarshalReuse(t *testing.T) { 7717 t.Run("Bytes", func(t *testing.T) { 7718 in := make([]byte, 3) 7719 want := &in[0] 7720 if err := Unmarshal([]byte(`"AQID"`), &in); err != nil { 7721 t.Fatalf("Unmarshal error: %v", err) 7722 } 7723 got := &in[0] 7724 if got != want { 7725 t.Errorf("input buffer was not reused") 7726 } 7727 }) 7728 t.Run("Slices", func(t *testing.T) { 7729 in := make([]int, 3) 7730 want := &in[0] 7731 if err := Unmarshal([]byte(`[0,1,2]`), &in); err != nil { 7732 t.Fatalf("Unmarshal error: %v", err) 7733 } 7734 got := &in[0] 7735 if got != want { 7736 t.Errorf("input slice was not reused") 7737 } 7738 }) 7739 t.Run("Maps", func(t *testing.T) { 7740 in := make(map[string]string) 7741 want := reflect.ValueOf(in).Pointer() 7742 if err := Unmarshal([]byte(`{"key":"value"}`), &in); err != nil { 7743 t.Fatalf("Unmarshal error: %v", err) 7744 } 7745 got := reflect.ValueOf(in).Pointer() 7746 if got != want { 7747 t.Errorf("input map was not reused") 7748 } 7749 }) 7750 t.Run("Pointers", func(t *testing.T) { 7751 in := addr(addr(addr("hello"))) 7752 want := **in 7753 if err := Unmarshal([]byte(`"goodbye"`), &in); err != nil { 7754 t.Fatalf("Unmarshal error: %v", err) 7755 } 7756 got := **in 7757 if got != want { 7758 t.Errorf("input pointer was not reused") 7759 } 7760 }) 7761 }