@@ -210,23 +210,23 @@ func (e TypeReflectCacheEntry) ToUnstructured(sv reflect.Value) (interface{}, er
210210
211211 case data [0 ] == '"' :
212212 var result string
213- err := json . Unmarshal (data , & result )
213+ err := unmarshal (data , & result )
214214 if err != nil {
215215 return nil , fmt .Errorf ("error decoding string from json: %v" , err )
216216 }
217217 return result , nil
218218
219219 case data [0 ] == '{' :
220220 result := make (map [string ]interface {})
221- err := json . Unmarshal (data , & result )
221+ err := unmarshal (data , & result )
222222 if err != nil {
223223 return nil , fmt .Errorf ("error decoding object from json: %v" , err )
224224 }
225225 return result , nil
226226
227227 case data [0 ] == '[' :
228228 result := make ([]interface {}, 0 )
229- err := json . Unmarshal (data , & result )
229+ err := unmarshal (data , & result )
230230 if err != nil {
231231 return nil , fmt .Errorf ("error decoding array from json: %v" , err )
232232 }
@@ -238,9 +238,9 @@ func (e TypeReflectCacheEntry) ToUnstructured(sv reflect.Value) (interface{}, er
238238 resultFloat float64
239239 err error
240240 )
241- if err = json . Unmarshal (data , & resultInt ); err == nil {
241+ if err = unmarshal (data , & resultInt ); err == nil {
242242 return resultInt , nil
243- } else if err = json . Unmarshal (data , & resultFloat ); err == nil {
243+ } else if err = unmarshal (data , & resultFloat ); err == nil {
244244 return resultFloat , nil
245245 } else {
246246 return nil , fmt .Errorf ("error decoding number from json: %v" , err )
@@ -363,3 +363,101 @@ func (c *typeReflectCache) update(updates reflectCacheMap) {
363363 }
364364 c .value .Store (newCacheMap )
365365}
366+
367+ // Below json Unmarshal is fromk8s.io/apimachinery/pkg/util/json
368+ // to handle number conversions as expected by Kubernetes
369+
370+ // limit recursive depth to prevent stack overflow errors
371+ const maxDepth = 10000
372+
373+ // unmarshal unmarshals the given data
374+ // If v is a *map[string]interface{}, numbers are converted to int64 or float64
375+ func unmarshal (data []byte , v interface {}) error {
376+ switch v := v .(type ) {
377+ case * map [string ]interface {}:
378+ // Build a decoder from the given data
379+ decoder := json .NewDecoder (bytes .NewBuffer (data ))
380+ // Preserve numbers, rather than casting to float64 automatically
381+ decoder .UseNumber ()
382+ // Run the decode
383+ if err := decoder .Decode (v ); err != nil {
384+ return err
385+ }
386+ // If the decode succeeds, post-process the map to convert json.Number objects to int64 or float64
387+ return convertMapNumbers (* v , 0 )
388+
389+ case * []interface {}:
390+ // Build a decoder from the given data
391+ decoder := json .NewDecoder (bytes .NewBuffer (data ))
392+ // Preserve numbers, rather than casting to float64 automatically
393+ decoder .UseNumber ()
394+ // Run the decode
395+ if err := decoder .Decode (v ); err != nil {
396+ return err
397+ }
398+ // If the decode succeeds, post-process the map to convert json.Number objects to int64 or float64
399+ return convertSliceNumbers (* v , 0 )
400+
401+ default :
402+ return json .Unmarshal (data , v )
403+ }
404+ }
405+
406+ // convertMapNumbers traverses the map, converting any json.Number values to int64 or float64.
407+ // values which are map[string]interface{} or []interface{} are recursively visited
408+ func convertMapNumbers (m map [string ]interface {}, depth int ) error {
409+ if depth > maxDepth {
410+ return fmt .Errorf ("exceeded max depth of %d" , maxDepth )
411+ }
412+
413+ var err error
414+ for k , v := range m {
415+ switch v := v .(type ) {
416+ case json.Number :
417+ m [k ], err = convertNumber (v )
418+ case map [string ]interface {}:
419+ err = convertMapNumbers (v , depth + 1 )
420+ case []interface {}:
421+ err = convertSliceNumbers (v , depth + 1 )
422+ }
423+ if err != nil {
424+ return err
425+ }
426+ }
427+ return nil
428+ }
429+
430+ // convertSliceNumbers traverses the slice, converting any json.Number values to int64 or float64.
431+ // values which are map[string]interface{} or []interface{} are recursively visited
432+ func convertSliceNumbers (s []interface {}, depth int ) error {
433+ if depth > maxDepth {
434+ return fmt .Errorf ("exceeded max depth of %d" , maxDepth )
435+ }
436+
437+ var err error
438+ for i , v := range s {
439+ switch v := v .(type ) {
440+ case json.Number :
441+ s [i ], err = convertNumber (v )
442+ case map [string ]interface {}:
443+ err = convertMapNumbers (v , depth + 1 )
444+ case []interface {}:
445+ err = convertSliceNumbers (v , depth + 1 )
446+ }
447+ if err != nil {
448+ return err
449+ }
450+ }
451+ return nil
452+ }
453+
454+ // convertNumber converts a json.Number to an int64 or float64, or returns an error
455+ func convertNumber (n json.Number ) (interface {}, error ) {
456+ // Attempt to convert to an int64 first
457+ if i , err := n .Int64 (); err == nil {
458+ return i , nil
459+ }
460+ // Return a float64 (default json.Decode() behavior)
461+ // An overflow will return an error
462+ return n .Float64 ()
463+ }
0 commit comments