unmarshal_json.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package decoder
  2. import (
  3. "context"
  4. "encoding/json"
  5. "unsafe"
  6. "github.com/goccy/go-json/internal/errors"
  7. "github.com/goccy/go-json/internal/runtime"
  8. )
  9. type unmarshalJSONDecoder struct {
  10. typ *runtime.Type
  11. structName string
  12. fieldName string
  13. }
  14. func newUnmarshalJSONDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalJSONDecoder {
  15. return &unmarshalJSONDecoder{
  16. typ: typ,
  17. structName: structName,
  18. fieldName: fieldName,
  19. }
  20. }
  21. func (d *unmarshalJSONDecoder) annotateError(cursor int64, err error) {
  22. switch e := err.(type) {
  23. case *errors.UnmarshalTypeError:
  24. e.Struct = d.structName
  25. e.Field = d.fieldName
  26. case *errors.SyntaxError:
  27. e.Offset = cursor
  28. }
  29. }
  30. func (d *unmarshalJSONDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
  31. s.skipWhiteSpace()
  32. start := s.cursor
  33. if err := s.skipValue(depth); err != nil {
  34. return err
  35. }
  36. src := s.buf[start:s.cursor]
  37. dst := make([]byte, len(src))
  38. copy(dst, src)
  39. v := *(*interface{})(unsafe.Pointer(&emptyInterface{
  40. typ: d.typ,
  41. ptr: p,
  42. }))
  43. switch v := v.(type) {
  44. case unmarshalerContext:
  45. var ctx context.Context
  46. if (s.Option.Flags & ContextOption) != 0 {
  47. ctx = s.Option.Context
  48. } else {
  49. ctx = context.Background()
  50. }
  51. if err := v.UnmarshalJSON(ctx, dst); err != nil {
  52. d.annotateError(s.cursor, err)
  53. return err
  54. }
  55. case json.Unmarshaler:
  56. if err := v.UnmarshalJSON(dst); err != nil {
  57. d.annotateError(s.cursor, err)
  58. return err
  59. }
  60. }
  61. return nil
  62. }
  63. func (d *unmarshalJSONDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
  64. buf := ctx.Buf
  65. cursor = skipWhiteSpace(buf, cursor)
  66. start := cursor
  67. end, err := skipValue(buf, cursor, depth)
  68. if err != nil {
  69. return 0, err
  70. }
  71. src := buf[start:end]
  72. dst := make([]byte, len(src))
  73. copy(dst, src)
  74. v := *(*interface{})(unsafe.Pointer(&emptyInterface{
  75. typ: d.typ,
  76. ptr: p,
  77. }))
  78. if (ctx.Option.Flags & ContextOption) != 0 {
  79. if err := v.(unmarshalerContext).UnmarshalJSON(ctx.Option.Context, dst); err != nil {
  80. d.annotateError(cursor, err)
  81. return 0, err
  82. }
  83. } else {
  84. if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil {
  85. d.annotateError(cursor, err)
  86. return 0, err
  87. }
  88. }
  89. return end, nil
  90. }