k8s.io/kube-openapi@v0.0.0-20240228011516-70dd3763d340/pkg/internal/third_party/go-json-experiment/json/arshal_any.go (about) 1 // Copyright 2022 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 "reflect" 8 9 // This files contains an optimized marshal and unmarshal implementation 10 // for the any type. This type is often used when the Go program has 11 // no knowledge of the JSON schema. This is a common enough occurrence 12 // to justify the complexity of adding logic for this. 13 14 func marshalValueAny(mo MarshalOptions, enc *Encoder, val any) error { 15 switch val := val.(type) { 16 case nil: 17 return enc.WriteToken(Null) 18 case bool: 19 return enc.WriteToken(Bool(val)) 20 case string: 21 return enc.WriteToken(String(val)) 22 case float64: 23 return enc.WriteToken(Float(val)) 24 case map[string]any: 25 return marshalObjectAny(mo, enc, val) 26 case []any: 27 return marshalArrayAny(mo, enc, val) 28 default: 29 v := newAddressableValue(reflect.TypeOf(val)) 30 v.Set(reflect.ValueOf(val)) 31 marshal := lookupArshaler(v.Type()).marshal 32 if mo.Marshalers != nil { 33 marshal, _ = mo.Marshalers.lookup(marshal, v.Type()) 34 } 35 return marshal(mo, enc, v) 36 } 37 } 38 39 func unmarshalValueAny(uo UnmarshalOptions, dec *Decoder) (any, error) { 40 switch k := dec.PeekKind(); k { 41 case '{': 42 return unmarshalObjectAny(uo, dec) 43 case '[': 44 return unmarshalArrayAny(uo, dec) 45 default: 46 var flags valueFlags 47 val, err := dec.readValue(&flags) 48 if err != nil { 49 return nil, err 50 } 51 switch val.Kind() { 52 case 'n': 53 return nil, nil 54 case 'f': 55 return false, nil 56 case 't': 57 return true, nil 58 case '"': 59 val = unescapeStringMayCopy(val, flags.isVerbatim()) 60 if dec.stringCache == nil { 61 dec.stringCache = new(stringCache) 62 } 63 return dec.stringCache.make(val), nil 64 case '0': 65 fv, _ := parseFloat(val, 64) // ignore error since readValue guarantees val is valid 66 return fv, nil 67 default: 68 panic("BUG: invalid kind: " + k.String()) 69 } 70 } 71 } 72 73 func marshalObjectAny(mo MarshalOptions, enc *Encoder, obj map[string]any) error { 74 // Check for cycles. 75 if enc.tokens.depth() > startDetectingCyclesAfter { 76 v := reflect.ValueOf(obj) 77 if err := enc.seenPointers.visit(v); err != nil { 78 return err 79 } 80 defer enc.seenPointers.leave(v) 81 } 82 83 // Optimize for marshaling an empty map without any preceding whitespace. 84 if len(obj) == 0 && !enc.options.multiline && !enc.tokens.last.needObjectName() { 85 enc.buf = enc.tokens.mayAppendDelim(enc.buf, '{') 86 enc.buf = append(enc.buf, "{}"...) 87 enc.tokens.last.increment() 88 if enc.needFlush() { 89 return enc.flush() 90 } 91 return nil 92 } 93 94 if err := enc.WriteToken(ObjectStart); err != nil { 95 return err 96 } 97 // A Go map guarantees that each entry has a unique key 98 // The only possibility of duplicates is due to invalid UTF-8. 99 if !enc.options.AllowInvalidUTF8 { 100 enc.tokens.last.disableNamespace() 101 } 102 if !mo.Deterministic || len(obj) <= 1 { 103 for name, val := range obj { 104 if err := enc.WriteToken(String(name)); err != nil { 105 return err 106 } 107 if err := marshalValueAny(mo, enc, val); err != nil { 108 return err 109 } 110 } 111 } else { 112 names := getStrings(len(obj)) 113 var i int 114 for name := range obj { 115 (*names)[i] = name 116 i++ 117 } 118 names.Sort() 119 for _, name := range *names { 120 if err := enc.WriteToken(String(name)); err != nil { 121 return err 122 } 123 if err := marshalValueAny(mo, enc, obj[name]); err != nil { 124 return err 125 } 126 } 127 putStrings(names) 128 } 129 if err := enc.WriteToken(ObjectEnd); err != nil { 130 return err 131 } 132 return nil 133 } 134 135 func unmarshalObjectAny(uo UnmarshalOptions, dec *Decoder) (map[string]any, error) { 136 tok, err := dec.ReadToken() 137 if err != nil { 138 return nil, err 139 } 140 k := tok.Kind() 141 switch k { 142 case 'n': 143 return nil, nil 144 case '{': 145 obj := make(map[string]any) 146 // A Go map guarantees that each entry has a unique key 147 // The only possibility of duplicates is due to invalid UTF-8. 148 if !dec.options.AllowInvalidUTF8 { 149 dec.tokens.last.disableNamespace() 150 } 151 for dec.PeekKind() != '}' { 152 tok, err := dec.ReadToken() 153 if err != nil { 154 return obj, err 155 } 156 name := tok.String() 157 158 // Manually check for duplicate names. 159 if _, ok := obj[name]; ok { 160 name := dec.previousBuffer() 161 err := &SyntacticError{str: "duplicate name " + string(name) + " in object"} 162 return obj, err.withOffset(dec.InputOffset() - int64(len(name))) 163 } 164 165 val, err := unmarshalValueAny(uo, dec) 166 obj[name] = val 167 if err != nil { 168 return obj, err 169 } 170 } 171 if _, err := dec.ReadToken(); err != nil { 172 return obj, err 173 } 174 return obj, nil 175 } 176 return nil, &SemanticError{action: "unmarshal", JSONKind: k, GoType: mapStringAnyType} 177 } 178 179 func marshalArrayAny(mo MarshalOptions, enc *Encoder, arr []any) error { 180 // Check for cycles. 181 if enc.tokens.depth() > startDetectingCyclesAfter { 182 v := reflect.ValueOf(arr) 183 if err := enc.seenPointers.visit(v); err != nil { 184 return err 185 } 186 defer enc.seenPointers.leave(v) 187 } 188 189 // Optimize for marshaling an empty slice without any preceding whitespace. 190 if len(arr) == 0 && !enc.options.multiline && !enc.tokens.last.needObjectName() { 191 enc.buf = enc.tokens.mayAppendDelim(enc.buf, '[') 192 enc.buf = append(enc.buf, "[]"...) 193 enc.tokens.last.increment() 194 if enc.needFlush() { 195 return enc.flush() 196 } 197 return nil 198 } 199 200 if err := enc.WriteToken(ArrayStart); err != nil { 201 return err 202 } 203 for _, val := range arr { 204 if err := marshalValueAny(mo, enc, val); err != nil { 205 return err 206 } 207 } 208 if err := enc.WriteToken(ArrayEnd); err != nil { 209 return err 210 } 211 return nil 212 } 213 214 func unmarshalArrayAny(uo UnmarshalOptions, dec *Decoder) ([]any, error) { 215 tok, err := dec.ReadToken() 216 if err != nil { 217 return nil, err 218 } 219 k := tok.Kind() 220 switch k { 221 case 'n': 222 return nil, nil 223 case '[': 224 arr := []any{} 225 for dec.PeekKind() != ']' { 226 val, err := unmarshalValueAny(uo, dec) 227 arr = append(arr, val) 228 if err != nil { 229 return arr, err 230 } 231 } 232 if _, err := dec.ReadToken(); err != nil { 233 return arr, err 234 } 235 return arr, nil 236 } 237 return nil, &SemanticError{action: "unmarshal", JSONKind: k, GoType: sliceAnyType} 238 }