mirror of https://github.com/k3s-io/k3s
make json serializer case sensitive
parent
dd69be30a5
commit
7b0ffb8410
|
@ -58,7 +58,6 @@ go_library(
|
|||
"//pkg/proxy/apis/kubeproxyconfig/scheme:go_default_library",
|
||||
"//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library",
|
||||
"//pkg/util/pointer:go_default_library",
|
||||
"//vendor/github.com/json-iterator/go:go_default_library",
|
||||
"//vendor/github.com/ugorji/go/codec:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
|
|
|
@ -23,7 +23,6 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/ugorji/go/codec"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
@ -31,8 +30,6 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
)
|
||||
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
|
||||
type configMutationFunc func(map[string]interface{}) error
|
||||
|
||||
// These migrations are a stop-gap until we get a properly-versioned configuration file for MasterConfiguration.
|
||||
|
|
|
@ -96,6 +96,7 @@ go_test(
|
|||
"//vendor/k8s.io/apimachinery/pkg/conversion: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/serializer/json:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
|
|
|
@ -37,6 +37,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
k8s_json "k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/streaming"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
@ -560,9 +561,10 @@ func BenchmarkDecodeIntoJSONCodecGenConfigFast(b *testing.B) {
|
|||
b.StopTimer()
|
||||
}
|
||||
|
||||
// BenchmarkDecodeIntoJSONCodecGenConfigCompatibleWithStandardLibrary
|
||||
// provides a baseline for JSON decode performance
|
||||
// with jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
// BenchmarkDecodeIntoJSONCodecGenConfigCompatibleWithStandardLibrary provides a
|
||||
// baseline for JSON decode performance with
|
||||
// jsoniter.ConfigCompatibleWithStandardLibrary, but with case sensitivity set
|
||||
// to true
|
||||
func BenchmarkDecodeIntoJSONCodecGenConfigCompatibleWithStandardLibrary(b *testing.B) {
|
||||
kcodec := testapi.Default.Codec()
|
||||
items := benchmarkItems(b)
|
||||
|
@ -577,9 +579,10 @@ func BenchmarkDecodeIntoJSONCodecGenConfigCompatibleWithStandardLibrary(b *testi
|
|||
}
|
||||
|
||||
b.ResetTimer()
|
||||
iter := k8s_json.CaseSensitiveJsonIterator()
|
||||
for i := 0; i < b.N; i++ {
|
||||
obj := v1.Pod{}
|
||||
if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(encoded[i%width], &obj); err != nil {
|
||||
if err := iter.Unmarshal(encoded[i%width], &obj); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,9 +21,9 @@ go_test(
|
|||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//vendor/github.com/ghodss/yaml:go_default_library",
|
||||
"//vendor/github.com/json-iterator/go:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
k8s_json "k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||
)
|
||||
|
||||
type GroupVersionHolder struct {
|
||||
|
@ -47,7 +47,8 @@ func TestGroupVersionUnmarshalJSON(t *testing.T) {
|
|||
t.Errorf("JSON codec failed to unmarshal input '%s': expected %+v, got %+v", c.input, c.expect, result.GV)
|
||||
}
|
||||
// test the json-iterator codec
|
||||
if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(c.input, &result); err != nil {
|
||||
iter := k8s_json.CaseSensitiveJsonIterator()
|
||||
if err := iter.Unmarshal(c.input, &result); err != nil {
|
||||
t.Errorf("json-iterator codec failed to unmarshal input '%v': %v", c.input, err)
|
||||
}
|
||||
if !reflect.DeepEqual(result.GV, c.expect) {
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
k8s_json "k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||
)
|
||||
|
||||
func TestVerbsUgorjiMarshalJSON(t *testing.T) {
|
||||
|
@ -45,7 +45,7 @@ func TestVerbsUgorjiMarshalJSON(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestVerbsUgorjiUnmarshalJSON(t *testing.T) {
|
||||
func TestVerbsUJsonIterUnmarshalJSON(t *testing.T) {
|
||||
cases := []struct {
|
||||
input string
|
||||
result APIResource
|
||||
|
@ -56,9 +56,10 @@ func TestVerbsUgorjiUnmarshalJSON(t *testing.T) {
|
|||
{`{"verbs":["delete"]}`, APIResource{Verbs: Verbs([]string{"delete"})}},
|
||||
}
|
||||
|
||||
iter := k8s_json.CaseSensitiveJsonIterator()
|
||||
for i, c := range cases {
|
||||
var result APIResource
|
||||
if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal([]byte(c.input), &result); err != nil {
|
||||
if err := iter.Unmarshal([]byte(c.input), &result); err != nil {
|
||||
t.Errorf("[%d] Failed to unmarshal input '%v': %v", i, c.input, err)
|
||||
}
|
||||
if !reflect.DeepEqual(result, c.result) {
|
||||
|
|
|
@ -93,6 +93,20 @@ func init() {
|
|||
jsoniter.RegisterTypeDecoderFunc("interface {}", decodeNumberAsInt64IfPossible)
|
||||
}
|
||||
|
||||
// CaseSensitiveJsonIterator returns a jsoniterator API that's configured to be
|
||||
// case-sensitive when unmarshalling, and otherwise compatible with
|
||||
// the encoding/json standard library.
|
||||
func CaseSensitiveJsonIterator() jsoniter.API {
|
||||
return jsoniter.Config{
|
||||
EscapeHTML: true,
|
||||
SortMapKeys: true,
|
||||
ValidateJsonRawMessage: true,
|
||||
CaseSensitive: true,
|
||||
}.Froze()
|
||||
}
|
||||
|
||||
var caseSensitiveJsonIterator = CaseSensitiveJsonIterator()
|
||||
|
||||
// gvkWithDefaults returns group kind and version defaulting from provided default
|
||||
func gvkWithDefaults(actual, defaultGVK schema.GroupVersionKind) schema.GroupVersionKind {
|
||||
if len(actual.Kind) == 0 {
|
||||
|
@ -157,7 +171,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i
|
|||
types, _, err := s.typer.ObjectKinds(into)
|
||||
switch {
|
||||
case runtime.IsNotRegisteredError(err), isUnstructured:
|
||||
if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(data, into); err != nil {
|
||||
if err := caseSensitiveJsonIterator.Unmarshal(data, into); err != nil {
|
||||
return nil, actual, err
|
||||
}
|
||||
return into, actual, nil
|
||||
|
@ -181,7 +195,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i
|
|||
return nil, actual, err
|
||||
}
|
||||
|
||||
if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(data, obj); err != nil {
|
||||
if err := caseSensitiveJsonIterator.Unmarshal(data, obj); err != nil {
|
||||
return nil, actual, err
|
||||
}
|
||||
return obj, actual, nil
|
||||
|
@ -190,7 +204,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i
|
|||
// Encode serializes the provided object to the given writer.
|
||||
func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error {
|
||||
if s.yaml {
|
||||
json, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(obj)
|
||||
json, err := caseSensitiveJsonIterator.Marshal(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -203,7 +217,7 @@ func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error {
|
|||
}
|
||||
|
||||
if s.pretty {
|
||||
data, err := jsoniter.ConfigCompatibleWithStandardLibrary.MarshalIndent(obj, "", " ")
|
||||
data, err := caseSensitiveJsonIterator.MarshalIndent(obj, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -30,10 +30,31 @@ import (
|
|||
|
||||
type testDecodable struct {
|
||||
Other string
|
||||
Value int `json:"value"`
|
||||
Value int `json:"value"`
|
||||
Spec DecodableSpec `json:"spec"`
|
||||
gvk schema.GroupVersionKind
|
||||
}
|
||||
|
||||
// DecodableSpec has 15 fields. json-iterator treats struct with more than 10
|
||||
// fields differently from struct that has less than 10 fields.
|
||||
type DecodableSpec struct {
|
||||
A int `json:"A"`
|
||||
B int `json:"B"`
|
||||
C int `json:"C"`
|
||||
D int `json:"D"`
|
||||
E int `json:"E"`
|
||||
F int `json:"F"`
|
||||
G int `json:"G"`
|
||||
H int `json:"h"`
|
||||
I int `json:"i"`
|
||||
J int `json:"j"`
|
||||
K int `json:"k"`
|
||||
L int `json:"l"`
|
||||
M int `json:"m"`
|
||||
N int `json:"n"`
|
||||
O int `json:"o"`
|
||||
}
|
||||
|
||||
func (d *testDecodable) GetObjectKind() schema.ObjectKind { return d }
|
||||
func (d *testDecodable) SetGroupVersionKind(gvk schema.GroupVersionKind) { d.gvk = gvk }
|
||||
func (d *testDecodable) GroupVersionKind() schema.GroupVersionKind { return d.gvk }
|
||||
|
@ -221,6 +242,28 @@ func TestDecode(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
// Unmarshalling is case-sensitive
|
||||
{
|
||||
// "VaLue" should have been "value"
|
||||
data: []byte(`{"kind":"Test","apiVersion":"other/blah","VaLue":1,"Other":"test"}`),
|
||||
into: &testDecodable{},
|
||||
typer: &mockTyper{err: runtime.NewNotRegisteredErrForKind(schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})},
|
||||
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
|
||||
expectedObject: &testDecodable{
|
||||
Other: "test",
|
||||
},
|
||||
},
|
||||
// Unmarshalling is case-sensitive for big struct.
|
||||
{
|
||||
// "b" should have been "B", "I" should have been "i"
|
||||
data: []byte(`{"kind":"Test","apiVersion":"other/blah","spec": {"A": 1, "b": 2, "h": 3, "I": 4}}`),
|
||||
into: &testDecodable{},
|
||||
typer: &mockTyper{err: runtime.NewNotRegisteredErrForKind(schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})},
|
||||
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
|
||||
expectedObject: &testDecodable{
|
||||
Spec: DecodableSpec{A: 1, H: 3},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range testCases {
|
||||
|
|
Loading…
Reference in New Issue