unmarshal_json.go 2.4 KB

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