mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 13:37:30 +00:00
Report parsing error in json serializer
This commit is contained in:
parent
6d3f5b75f5
commit
b76e512f8f
@ -22,6 +22,7 @@ go_library(
|
|||||||
deps = [
|
deps = [
|
||||||
"//vendor/github.com/ghodss/yaml:go_default_library",
|
"//vendor/github.com/ghodss/yaml:go_default_library",
|
||||||
"//vendor/github.com/json-iterator/go:go_default_library",
|
"//vendor/github.com/json-iterator/go:go_default_library",
|
||||||
|
"//vendor/github.com/modern-go/reflect2:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
"github.com/modern-go/reflect2"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
@ -68,12 +69,24 @@ type Serializer struct {
|
|||||||
var _ runtime.Serializer = &Serializer{}
|
var _ runtime.Serializer = &Serializer{}
|
||||||
var _ recognizer.RecognizingDecoder = &Serializer{}
|
var _ recognizer.RecognizingDecoder = &Serializer{}
|
||||||
|
|
||||||
func init() {
|
type customNumberExtension struct {
|
||||||
// Force jsoniter to decode number to interface{} via ints, if possible.
|
jsoniter.DummyExtension
|
||||||
decodeNumberAsInt64IfPossible := func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
}
|
||||||
|
|
||||||
|
func (cne *customNumberExtension) CreateDecoder(typ reflect2.Type) jsoniter.ValDecoder {
|
||||||
|
if typ.String() == "interface {}" {
|
||||||
|
return customNumberDecoder{}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type customNumberDecoder struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (customNumberDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||||
switch iter.WhatIsNext() {
|
switch iter.WhatIsNext() {
|
||||||
case jsoniter.NumberValue:
|
case jsoniter.NumberValue:
|
||||||
var number json.Number
|
var number jsoniter.Number
|
||||||
iter.ReadVal(&number)
|
iter.ReadVal(&number)
|
||||||
i64, err := strconv.ParseInt(string(number), 10, 64)
|
i64, err := strconv.ParseInt(string(number), 10, 64)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -85,26 +98,31 @@ func init() {
|
|||||||
*(*interface{})(ptr) = f64
|
*(*interface{})(ptr) = f64
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Not much we can do here.
|
iter.ReportError("DecodeNumber", err.Error())
|
||||||
default:
|
default:
|
||||||
*(*interface{})(ptr) = iter.Read()
|
*(*interface{})(ptr) = iter.Read()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jsoniter.RegisterTypeDecoderFunc("interface {}", decodeNumberAsInt64IfPossible)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CaseSensitiveJsonIterator returns a jsoniterator API that's configured to be
|
// CaseSensitiveJsonIterator returns a jsoniterator API that's configured to be
|
||||||
// case-sensitive when unmarshalling, and otherwise compatible with
|
// case-sensitive when unmarshalling, and otherwise compatible with
|
||||||
// the encoding/json standard library.
|
// the encoding/json standard library.
|
||||||
func CaseSensitiveJsonIterator() jsoniter.API {
|
func CaseSensitiveJsonIterator() jsoniter.API {
|
||||||
return jsoniter.Config{
|
config := jsoniter.Config{
|
||||||
EscapeHTML: true,
|
EscapeHTML: true,
|
||||||
SortMapKeys: true,
|
SortMapKeys: true,
|
||||||
ValidateJsonRawMessage: true,
|
ValidateJsonRawMessage: true,
|
||||||
CaseSensitive: true,
|
CaseSensitive: true,
|
||||||
}.Froze()
|
}.Froze()
|
||||||
|
// Force jsoniter to decode number to interface{} via int64/float64, if possible.
|
||||||
|
config.RegisterExtension(&customNumberExtension{})
|
||||||
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Private copy of jsoniter to try to shield against possible mutations
|
||||||
|
// from outside. Still does not protect from package level jsoniter.Register*() functions - someone calling them
|
||||||
|
// in some other library will mess with every usage of the jsoniter library in the whole program.
|
||||||
|
// See https://github.com/json-iterator/go/issues/265
|
||||||
var caseSensitiveJsonIterator = CaseSensitiveJsonIterator()
|
var caseSensitiveJsonIterator = CaseSensitiveJsonIterator()
|
||||||
|
|
||||||
// gvkWithDefaults returns group kind and version defaulting from provided default
|
// gvkWithDefaults returns group kind and version defaulting from provided default
|
||||||
|
@ -32,6 +32,7 @@ type testDecodable struct {
|
|||||||
Other string
|
Other string
|
||||||
Value int `json:"value"`
|
Value int `json:"value"`
|
||||||
Spec DecodableSpec `json:"spec"`
|
Spec DecodableSpec `json:"spec"`
|
||||||
|
Interface interface{} `json:"interface"`
|
||||||
gvk schema.GroupVersionKind
|
gvk schema.GroupVersionKind
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,6 +243,15 @@ func TestDecode(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// Error on invalid number
|
||||||
|
{
|
||||||
|
data: []byte(`{"kind":"Test","apiVersion":"other/blah","interface":1e1000}`),
|
||||||
|
creater: &mockCreater{obj: &testDecodable{}},
|
||||||
|
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
|
||||||
|
errFn: func(err error) bool {
|
||||||
|
return strings.Contains(err.Error(), `json_test.testDecodable.Interface: DecodeNumber: strconv.ParseFloat: parsing "1e1000": value out of range`)
|
||||||
|
},
|
||||||
|
},
|
||||||
// Unmarshalling is case-sensitive
|
// Unmarshalling is case-sensitive
|
||||||
{
|
{
|
||||||
// "VaLue" should have been "value"
|
// "VaLue" should have been "value"
|
||||||
|
Loading…
Reference in New Issue
Block a user