| |
| |
| |
|
|
| |
|
|
| package json |
|
|
| import ( |
| "bytes" |
| "errors" |
| "io" |
| "reflect" |
| "slices" |
|
|
| "encoding/json/internal/jsonflags" |
| "encoding/json/internal/jsonopts" |
| "encoding/json/internal/jsonwire" |
| "encoding/json/jsontext" |
| ) |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| var errRawInlinedNotObject = errors.New("inlined raw value must be a JSON object") |
|
|
| var jsontextValueType = reflect.TypeFor[jsontext.Value]() |
|
|
| |
| func marshalInlinedFallbackAll(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct, f *structField, insertUnquotedName func([]byte) bool) error { |
| v := addressableValue{va.Field(f.index0), va.forcedAddr} |
| if len(f.index) > 0 { |
| v = v.fieldByIndex(f.index, false) |
| if !v.IsValid() { |
| return nil |
| } |
| } |
| v = v.indirect(false) |
| if !v.IsValid() { |
| return nil |
| } |
|
|
| if v.Type() == jsontextValueType { |
| b, _ := reflect.TypeAssert[jsontext.Value](v.Value) |
| if len(b) == 0 { |
| return nil |
| } |
|
|
| dec := export.GetBufferedDecoder(b) |
| defer export.PutBufferedDecoder(dec) |
| xd := export.Decoder(dec) |
| xd.Flags.Set(jsonflags.AllowDuplicateNames | jsonflags.AllowInvalidUTF8 | 1) |
|
|
| tok, err := dec.ReadToken() |
| if err != nil { |
| if err == io.EOF { |
| err = io.ErrUnexpectedEOF |
| } |
| return newMarshalErrorBefore(enc, v.Type(), err) |
| } |
| if tok.Kind() != '{' { |
| return newMarshalErrorBefore(enc, v.Type(), errRawInlinedNotObject) |
| } |
| for dec.PeekKind() != '}' { |
| |
| var flags jsonwire.ValueFlags |
| val, err := xd.ReadValue(&flags) |
| if err != nil { |
| return newMarshalErrorBefore(enc, v.Type(), err) |
| } |
| if insertUnquotedName != nil { |
| name := jsonwire.UnquoteMayCopy(val, flags.IsVerbatim()) |
| if !insertUnquotedName(name) { |
| return newDuplicateNameError(enc.StackPointer().Parent(), val, enc.OutputOffset()) |
| } |
| } |
| if err := enc.WriteValue(val); err != nil { |
| return err |
| } |
|
|
| |
| val, err = xd.ReadValue(&flags) |
| if err != nil { |
| return newMarshalErrorBefore(enc, v.Type(), err) |
| } |
| if err := enc.WriteValue(val); err != nil { |
| return err |
| } |
| } |
| if _, err := dec.ReadToken(); err != nil { |
| return newMarshalErrorBefore(enc, v.Type(), err) |
| } |
| if err := xd.CheckEOF(); err != nil { |
| return newMarshalErrorBefore(enc, v.Type(), err) |
| } |
| return nil |
| } else { |
| m := v |
| n := m.Len() |
| if n == 0 { |
| return nil |
| } |
| mk := newAddressableValue(m.Type().Key()) |
| mv := newAddressableValue(m.Type().Elem()) |
| marshalKey := func(mk addressableValue) error { |
| b, err := jsonwire.AppendQuote(enc.AvailableBuffer(), mk.String(), &mo.Flags) |
| if err != nil { |
| return newMarshalErrorBefore(enc, m.Type().Key(), err) |
| } |
| if insertUnquotedName != nil { |
| isVerbatim := bytes.IndexByte(b, '\\') < 0 |
| name := jsonwire.UnquoteMayCopy(b, isVerbatim) |
| if !insertUnquotedName(name) { |
| return newDuplicateNameError(enc.StackPointer().Parent(), b, enc.OutputOffset()) |
| } |
| } |
| return enc.WriteValue(b) |
| } |
| marshalVal := f.fncs.marshal |
| if mo.Marshalers != nil { |
| marshalVal, _ = mo.Marshalers.(*Marshalers).lookup(marshalVal, mv.Type()) |
| } |
| if !mo.Flags.Get(jsonflags.Deterministic) || n <= 1 { |
| for iter := m.MapRange(); iter.Next(); { |
| mk.SetIterKey(iter) |
| if err := marshalKey(mk); err != nil { |
| return err |
| } |
| mv.Set(iter.Value()) |
| if err := marshalVal(enc, mv, mo); err != nil { |
| return err |
| } |
| } |
| } else { |
| names := getStrings(n) |
| for i, iter := 0, m.Value.MapRange(); i < n && iter.Next(); i++ { |
| mk.SetIterKey(iter) |
| (*names)[i] = mk.String() |
| } |
| slices.Sort(*names) |
| for _, name := range *names { |
| mk.SetString(name) |
| if err := marshalKey(mk); err != nil { |
| return err |
| } |
| |
| mv.Set(m.MapIndex(mk.Value)) |
| if err := marshalVal(enc, mv, mo); err != nil { |
| return err |
| } |
| } |
| putStrings(names) |
| } |
| return nil |
| } |
| } |
|
|
| |
| func unmarshalInlinedFallbackNext(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct, f *structField, quotedName, unquotedName []byte) error { |
| v := addressableValue{va.Field(f.index0), va.forcedAddr} |
| if len(f.index) > 0 { |
| v = v.fieldByIndex(f.index, true) |
| } |
| v = v.indirect(true) |
|
|
| if v.Type() == jsontextValueType { |
| b, _ := reflect.TypeAssert[*jsontext.Value](v.Addr()) |
| if len(*b) == 0 { |
| *b = append(*b, '{') |
| } else { |
| *b = jsonwire.TrimSuffixWhitespace(*b) |
| if jsonwire.HasSuffixByte(*b, '}') { |
| |
| |
| *b = jsonwire.TrimSuffixByte(*b, '}') |
| *b = jsonwire.TrimSuffixWhitespace(*b) |
| if !jsonwire.HasSuffixByte(*b, ',') && !jsonwire.HasSuffixByte(*b, '{') { |
| *b = append(*b, ',') |
| } |
| } else { |
| return newUnmarshalErrorAfterWithSkipping(dec, v.Type(), errRawInlinedNotObject) |
| } |
| } |
| *b = append(*b, quotedName...) |
| *b = append(*b, ':') |
| val, err := dec.ReadValue() |
| if err != nil { |
| return err |
| } |
| *b = append(*b, val...) |
| *b = append(*b, '}') |
| return nil |
| } else { |
| name := string(unquotedName) |
|
|
| m := v |
| if m.IsNil() { |
| m.Set(reflect.MakeMap(m.Type())) |
| } |
| mk := reflect.ValueOf(name) |
| if mkt := m.Type().Key(); mkt != stringType { |
| mk = mk.Convert(mkt) |
| } |
| mv := newAddressableValue(m.Type().Elem()) |
| if v2 := m.MapIndex(mk); v2.IsValid() { |
| mv.Set(v2) |
| } |
|
|
| unmarshal := f.fncs.unmarshal |
| if uo.Unmarshalers != nil { |
| unmarshal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshal, mv.Type()) |
| } |
| err := unmarshal(dec, mv, uo) |
| m.SetMapIndex(mk, mv.Value) |
| if err != nil { |
| return err |
| } |
| return nil |
| } |
| } |
|
|