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