package jsonimport (    "encoding/json"    "io"    "strconv"    "unsafe"    jsoniter "github.com/json-iterator/go"    "github.com/modern-go/reflect2"    "sigs.k8s.io/yaml"    "k8s.io/apimachinery/pkg/runtime"    "k8s.io/apimachinery/pkg/runtime/schema"    "k8s.io/apimachinery/pkg/runtime/serializer/recognizer"    "k8s.io/apimachinery/pkg/util/framer"    utilyaml "k8s.io/apimachinery/pkg/util/yaml"    "k8s.io/klog")var _ runtime.Serializer = &Serializer{}var _ recognizer.RecognizingDecoder = &Serializer{}// Private copies 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/265var caseSensitiveJsonIterator = CaseSensitiveJsonIterator()var strictCaseSensitiveJsonIterator = StrictCaseSensitiveJsonIterator()func NewSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper, pretty bool) *Serializer {    return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{false, pretty, false})}func NewYAMLSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper) *Serializer {    return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{true, false, false})}func NewSerializerWithOptions(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper, options SerializerOptions) *Serializer {    return &Serializer{        meta:       meta,        creater:    creater,        typer:      typer,        options:    options,        identifier: identifier(options),    }}type Serializer struct {    meta       MetaFactory    options    SerializerOptions    creater    runtime.ObjectCreater    typer      runtime.ObjectTyper    identifier runtime.Identifier}type SerializerOptions struct {    Yaml   bool    Pretty bool    Strict bool}type customNumberExtension struct {    jsoniter.DummyExtension}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() {    case jsoniter.NumberValue:        var number jsoniter.Number        iter.ReadVal(&number)        i64, err := strconv.ParseInt(string(number), 10, 64)        if err == nil {            *(*interface{})(ptr) = i64            return        }        f64, err := strconv.ParseFloat(string(number), 64)        if err == nil {            *(*interface{})(ptr) = f64            return        }        iter.ReportError("DecodeNumber", err.Error())    default:        *(*interface{})(ptr) = iter.Read()    }}// Decode attempts to convert the provided data into YAML or JSON, extract the stored schema kind, apply the provided default gvk, and then// load that data into an object matching the desired schema kind or the provided into.// If into is *runtime.Unknown, the raw data will be extracted and no decoding will be performed.// If into is not registered with the typer, then the object will be straight decoded using normal JSON/YAML unmarshalling.// If into is provided and the original data is not fully qualified with kind/version/group, the type of the into will be used to alter the returned gvk.// If into is nil or data's gvk different from into's gvk, it will generate a new Object with ObjectCreater.New(gvk)// On success or most errors, the method will return the calculated schema kind.// The gvk calculate priority will be originalData > default gvk > intofunc (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {    // 反序列化    data := originalData    if s.options.Yaml {        altered, err := yaml.YAMLToJSON(data)        if err != nil {            return nil, nil, err        }        data = altered    }    // 获取gvk信息    // 先反序列化获取gvk信息    // 然后和默认gvk diff,返回实际的gvk信息    actual, err := s.meta.Interpret(data)    if err != nil {        return nil, nil, err    }    if gvk != nil {        *actual = gvkWithDefaults(*actual, *gvk)    }    if unk, ok := into.(*runtime.Unknown); ok && unk != nil {        unk.Raw = originalData        unk.ContentType = runtime.ContentTypeJSON        unk.GetObjectKind().SetGroupVersionKind(*actual)        return unk, actual, nil    }    if into != nil {        // 动态客户端一般会用此obj(某些语言没有go对应的struct)        _, isUnstructured := into.(runtime.Unstructured)        types, _, err := s.typer.ObjectKinds(into)        switch {        case runtime.IsNotRegisteredError(err), isUnstructured:            if err := caseSensitiveJsonIterator.Unmarshal(data, into); err != nil {                return nil, actual, err            }            return into, actual, nil        case err != nil:            return nil, actual, err        default:            *actual = gvkWithDefaults(*actual, types[0])        }    }    if len(actual.Kind) == 0 {        return nil, actual, runtime.NewMissingKindErr(string(originalData))    }    if len(actual.Version) == 0 {        return nil, actual, runtime.NewMissingVersionErr(string(originalData))    }    // use the target if necessary    obj, err := runtime.UseOrCreateObject(s.typer, s.creater, *actual, into)    if err != nil {        return nil, actual, err    }    if err := caseSensitiveJsonIterator.Unmarshal(data, obj); err != nil {        return nil, actual, err    }    // If the deserializer is non-strict, return successfully here.    if !s.options.Strict {        return obj, actual, nil    }    // In strict mode pass the data trough the YAMLToJSONStrict converter.    // This is done to catch duplicate fields regardless of encoding (JSON or YAML). For JSON data,    // the output would equal the input, unless there is a parsing error such as duplicate fields.    // As we know this was successful in the non-strict case, the only error that may be returned here    // is because of the newly-added strictness. hence we know we can return the typed strictDecoderError    // the actual error is that the object contains duplicate fields.    altered, err := yaml.YAMLToJSONStrict(originalData)    if err != nil {        return nil, actual, runtime.NewStrictDecodingError(err.Error(), string(originalData))    }    // As performance is not an issue for now for the strict deserializer (one has regardless to do    // the unmarshal twice), we take the sanitized, altered data that is guaranteed to have no duplicated    // fields, and unmarshal this into a copy of the already-populated obj. Any error that occurs here is    // due to that a matching field doesn't exist in the object. hence we can return a typed strictDecoderError,    // the actual error is that the object contains unknown field.    strictObj := obj.DeepCopyObject()    if err := strictCaseSensitiveJsonIterator.Unmarshal(altered, strictObj); err != nil {        return nil, actual, runtime.NewStrictDecodingError(err.Error(), string(originalData))    }    // Always return the same object as the non-strict serializer to avoid any deviations.    return obj, actual, nil}// Encode serializes the provided object to the given writer.func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error {    if co, ok := obj.(runtime.CacheableObject); ok {        return co.CacheEncode(s.Identifier(), s.doEncode, w)    }    return s.doEncode(obj, w)}func (s *Serializer) doEncode(obj runtime.Object, w io.Writer) error {    if s.options.Yaml {        jsonData, err := caseSensitiveJsonIterator.Marshal(obj)        if err != nil {            return err        }        data, err := yaml.JSONToYAML(jsonData)        if err != nil {            return err        }        _, err = w.Write(data)        return err    }    if s.options.Pretty {        data, err := caseSensitiveJsonIterator.MarshalIndent(obj, "", "  ")        if err != nil {            return err        }        _, err = w.Write(data)        return err    }    encoder := json.NewEncoder(w)    return encoder.Encode(obj)}func (s *Serializer) Identifier() runtime.Identifier {    return s.identifier}func (s *Serializer) RecognizesData(peek io.Reader) (ok, unknown bool, err error) {    if s.options.Yaml {        return false, true, nil    }    _, _, ok = utilyaml.GuessJSONStream(peek, 2048)    return ok, false, nil}var Framer = jsonFramer{}type jsonFramer struct{}func (jsonFramer) NewFrameWriter(w io.Writer) io.Writer {    return w}func (jsonFramer) NewFrameReader(r io.ReadCloser) io.ReadCloser {    return framer.NewJSONFramedReader(r)}var YAMLFramer = yamlFramer{}type yamlFramer struct{}func (yamlFramer) NewFrameWriter(w io.Writer) io.Writer {    return yamlFrameWriter{w}}func (yamlFramer) NewFrameReader(r io.ReadCloser) io.ReadCloser {    return utilyaml.NewDocumentDecoder(r)}type yamlFrameWriter struct {    w io.Writer}func (w yamlFrameWriter) Write(data []byte) (n int, err error) {    if _, err := w.w.Write([]byte("---\n")); err != nil {        return 0, err    }    return w.w.Write(data)}//---------------------------------------//---------------工具函数-----------------//---------------------------------------// 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 {    config := jsoniter.Config{        EscapeHTML:             true,        SortMapKeys:            true,        ValidateJsonRawMessage: true,        CaseSensitive:          true,    }.Froze()    // Force jsoniter to decode number to interface{} via int64/float64, if possible.    config.RegisterExtension(&customNumberExtension{})    return config}// StrictCaseSensitiveJsonIterator returns a jsoniterator API that's configured to be// case-sensitive, but also disallows unknown fields when unmarshalling. It is compatible with// the encoding/json standard library.func StrictCaseSensitiveJsonIterator() jsoniter.API {    config := jsoniter.Config{        EscapeHTML:             true,        SortMapKeys:            true,        ValidateJsonRawMessage: true,        CaseSensitive:          true,        DisallowUnknownFields:  true,    }.Froze()    // Force jsoniter to decode number to interface{} via int64/float64, if possible.    config.RegisterExtension(&customNumberExtension{})    return config}func gvkWithDefaults(actual, defaultGVK schema.GroupVersionKind) schema.GroupVersionKind {    if len(actual.Kind) == 0 {        actual.Kind = defaultGVK.Kind    }    if len(actual.Version) == 0 && len(actual.Group) == 0 {        actual.Group = defaultGVK.Group        actual.Version = defaultGVK.Version    }    if len(actual.Version) == 0 && actual.Group == defaultGVK.Group {        actual.Version = defaultGVK.Version    }    return actual}func identifier(options SerializerOptions) runtime.Identifier {    result := map[string]string{        "name":   "json",        "yaml":   strconv.FormatBool(options.Yaml),        "pretty": strconv.FormatBool(options.Pretty),    }    identifier, err := json.Marshal(result)    if err != nil {        klog.Fatalf("Failed marshaling identifier for json Serializer: %v", err)    }    return runtime.Identifier(identifier)}