k8s.io/kube-openapi@v0.0.0-20240228011516-70dd3763d340/pkg/internal/third_party/go-json-experiment/json/arshal_inlined.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 "errors" 10 "reflect" 11 ) 12 13 // This package supports "inlining" a Go struct field, where the contents 14 // of the serialized field (which must be a JSON object) are treated as if 15 // they are part of the parent Go struct (which represents a JSON object). 16 // 17 // Generally, inlined fields are of a Go struct type, where the fields of the 18 // nested struct are virtually hoisted up to the parent struct using rules 19 // similar to how Go embedding works (but operating within the JSON namespace). 20 // 21 // However, inlined fields may also be of a Go map type with a string key 22 // or a RawValue. Such inlined fields are called "fallback" fields since they 23 // represent any arbitrary JSON object member. Explicitly named fields take 24 // precedence over the inlined fallback. Only one inlined fallback is allowed. 25 26 var rawValueType = reflect.TypeOf((*RawValue)(nil)).Elem() 27 28 // marshalInlinedFallbackAll marshals all the members in an inlined fallback. 29 func marshalInlinedFallbackAll(mo MarshalOptions, enc *Encoder, va addressableValue, f *structField, insertUnquotedName func([]byte) bool) error { 30 v := addressableValue{va.Field(f.index[0])} // addressable if struct value is addressable 31 if len(f.index) > 1 { 32 v = v.fieldByIndex(f.index[1:], false) 33 if !v.IsValid() { 34 return nil // implies a nil inlined field 35 } 36 } 37 v = v.indirect(false) 38 if !v.IsValid() { 39 return nil 40 } 41 42 if v.Type() == rawValueType { 43 b := v.Interface().(RawValue) 44 if len(b) == 0 { // TODO: Should this be nil? What if it were all whitespace? 45 return nil 46 } 47 48 dec := getBufferedDecoder(b, DecodeOptions{AllowDuplicateNames: true, AllowInvalidUTF8: true}) 49 defer putBufferedDecoder(dec) 50 51 tok, err := dec.ReadToken() 52 if err != nil { 53 return &SemanticError{action: "marshal", GoType: rawValueType, Err: err} 54 } 55 if tok.Kind() != '{' { 56 err := errors.New("inlined raw value must be a JSON object") 57 return &SemanticError{action: "marshal", JSONKind: tok.Kind(), GoType: rawValueType, Err: err} 58 } 59 for dec.PeekKind() != '}' { 60 // Parse the JSON object name. 61 var flags valueFlags 62 val, err := dec.readValue(&flags) 63 if err != nil { 64 return &SemanticError{action: "marshal", GoType: rawValueType, Err: err} 65 } 66 if insertUnquotedName != nil { 67 name := unescapeStringMayCopy(val, flags.isVerbatim()) 68 if !insertUnquotedName(name) { 69 return &SyntacticError{str: "duplicate name " + string(val) + " in object"} 70 } 71 } 72 if err := enc.WriteValue(val); err != nil { 73 return err 74 } 75 76 // Parse the JSON object value. 77 val, err = dec.readValue(&flags) 78 if err != nil { 79 return &SemanticError{action: "marshal", GoType: rawValueType, Err: err} 80 } 81 if err := enc.WriteValue(val); err != nil { 82 return err 83 } 84 } 85 if _, err := dec.ReadToken(); err != nil { 86 return &SemanticError{action: "marshal", GoType: rawValueType, Err: err} 87 } 88 if err := dec.checkEOF(); err != nil { 89 return &SemanticError{action: "marshal", GoType: rawValueType, Err: err} 90 } 91 return nil 92 } else { 93 m := v // must be a map[string]V 94 n := m.Len() 95 if n == 0 { 96 return nil 97 } 98 mk := newAddressableValue(stringType) 99 mv := newAddressableValue(m.Type().Elem()) 100 marshalKey := func(mk addressableValue) error { 101 b, err := appendString(enc.UnusedBuffer(), mk.String(), !enc.options.AllowInvalidUTF8, nil) 102 if err != nil { 103 return err 104 } 105 if insertUnquotedName != nil { 106 isVerbatim := bytes.IndexByte(b, '\\') < 0 107 name := unescapeStringMayCopy(b, isVerbatim) 108 if !insertUnquotedName(name) { 109 return &SyntacticError{str: "duplicate name " + string(b) + " in object"} 110 } 111 } 112 return enc.WriteValue(b) 113 } 114 marshalVal := f.fncs.marshal 115 if mo.Marshalers != nil { 116 marshalVal, _ = mo.Marshalers.lookup(marshalVal, mv.Type()) 117 } 118 if !mo.Deterministic || n <= 1 { 119 for iter := m.MapRange(); iter.Next(); { 120 mk.SetIterKey(iter) 121 if err := marshalKey(mk); err != nil { 122 return err 123 } 124 mv.Set(iter.Value()) 125 if err := marshalVal(mo, enc, mv); err != nil { 126 return err 127 } 128 } 129 } else { 130 names := getStrings(n) 131 for i, iter := 0, m.Value.MapRange(); i < n && iter.Next(); i++ { 132 mk.SetIterKey(iter) 133 (*names)[i] = mk.String() 134 } 135 names.Sort() 136 for _, name := range *names { 137 mk.SetString(name) 138 if err := marshalKey(mk); err != nil { 139 return err 140 } 141 // TODO(https://go.dev/issue/57061): Use mv.SetMapIndexOf. 142 mv.Set(m.MapIndex(mk.Value)) 143 if err := marshalVal(mo, enc, mv); err != nil { 144 return err 145 } 146 } 147 putStrings(names) 148 } 149 return nil 150 } 151 } 152 153 // unmarshalInlinedFallbackNext unmarshals only the next member in an inlined fallback. 154 func unmarshalInlinedFallbackNext(uo UnmarshalOptions, dec *Decoder, va addressableValue, f *structField, quotedName, unquotedName []byte) error { 155 v := addressableValue{va.Field(f.index[0])} // addressable if struct value is addressable 156 if len(f.index) > 1 { 157 v = v.fieldByIndex(f.index[1:], true) 158 } 159 v = v.indirect(true) 160 161 if v.Type() == rawValueType { 162 b := v.Addr().Interface().(*RawValue) 163 if len(*b) == 0 { // TODO: Should this be nil? What if it were all whitespace? 164 *b = append(*b, '{') 165 } else { 166 *b = trimSuffixWhitespace(*b) 167 if hasSuffixByte(*b, '}') { 168 // TODO: When merging into an object for the first time, 169 // should we verify that it is valid? 170 *b = trimSuffixByte(*b, '}') 171 *b = trimSuffixWhitespace(*b) 172 if !hasSuffixByte(*b, ',') && !hasSuffixByte(*b, '{') { 173 *b = append(*b, ',') 174 } 175 } else { 176 err := errors.New("inlined raw value must be a JSON object") 177 return &SemanticError{action: "unmarshal", GoType: rawValueType, Err: err} 178 } 179 } 180 *b = append(*b, quotedName...) 181 *b = append(*b, ':') 182 rawValue, err := dec.ReadValue() 183 if err != nil { 184 return err 185 } 186 *b = append(*b, rawValue...) 187 *b = append(*b, '}') 188 return nil 189 } else { 190 name := string(unquotedName) // TODO: Intern this? 191 192 m := v // must be a map[string]V 193 if m.IsNil() { 194 m.Set(reflect.MakeMap(m.Type())) 195 } 196 mk := reflect.ValueOf(name) 197 mv := newAddressableValue(v.Type().Elem()) // TODO: Cache across calls? 198 if v2 := m.MapIndex(mk); v2.IsValid() { 199 mv.Set(v2) 200 } 201 202 unmarshal := f.fncs.unmarshal 203 if uo.Unmarshalers != nil { 204 unmarshal, _ = uo.Unmarshalers.lookup(unmarshal, mv.Type()) 205 } 206 err := unmarshal(uo, dec, mv) 207 m.SetMapIndex(mk, mv.Value) 208 if err != nil { 209 return err 210 } 211 return nil 212 } 213 }