1. package json
    2. import (
    3. "encoding/json"
    4. "io"
    5. "strconv"
    6. "unsafe"
    7. jsoniter "github.com/json-iterator/go"
    8. "github.com/modern-go/reflect2"
    9. "sigs.k8s.io/yaml"
    10. "k8s.io/apimachinery/pkg/runtime"
    11. "k8s.io/apimachinery/pkg/runtime/schema"
    12. "k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
    13. "k8s.io/apimachinery/pkg/util/framer"
    14. utilyaml "k8s.io/apimachinery/pkg/util/yaml"
    15. "k8s.io/klog"
    16. )
    17. var _ runtime.Serializer = &Serializer{}
    18. var _ recognizer.RecognizingDecoder = &Serializer{}
    19. // Private copies of jsoniter to try to shield against possible mutations
    20. // from outside. Still does not protect from package level jsoniter.Register*() functions - someone calling them
    21. // in some other library will mess with every usage of the jsoniter library in the whole program.
    22. // See https://github.com/json-iterator/go/issues/265
    23. var caseSensitiveJsonIterator = CaseSensitiveJsonIterator()
    24. var strictCaseSensitiveJsonIterator = StrictCaseSensitiveJsonIterator()
    25. func NewSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper, pretty bool) *Serializer {
    26. return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{false, pretty, false})
    27. }
    28. func NewYAMLSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper) *Serializer {
    29. return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{true, false, false})
    30. }
    31. func NewSerializerWithOptions(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper, options SerializerOptions) *Serializer {
    32. return &Serializer{
    33. meta: meta,
    34. creater: creater,
    35. typer: typer,
    36. options: options,
    37. identifier: identifier(options),
    38. }
    39. }
    40. type Serializer struct {
    41. meta MetaFactory
    42. options SerializerOptions
    43. creater runtime.ObjectCreater
    44. typer runtime.ObjectTyper
    45. identifier runtime.Identifier
    46. }
    47. type SerializerOptions struct {
    48. Yaml bool
    49. Pretty bool
    50. Strict bool
    51. }
    52. type customNumberExtension struct {
    53. jsoniter.DummyExtension
    54. }
    55. func (cne *customNumberExtension) CreateDecoder(typ reflect2.Type) jsoniter.ValDecoder {
    56. if typ.String() == "interface {}" {
    57. return customNumberDecoder{}
    58. }
    59. return nil
    60. }
    61. type customNumberDecoder struct {
    62. }
    63. func (customNumberDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
    64. switch iter.WhatIsNext() {
    65. case jsoniter.NumberValue:
    66. var number jsoniter.Number
    67. iter.ReadVal(&number)
    68. i64, err := strconv.ParseInt(string(number), 10, 64)
    69. if err == nil {
    70. *(*interface{})(ptr) = i64
    71. return
    72. }
    73. f64, err := strconv.ParseFloat(string(number), 64)
    74. if err == nil {
    75. *(*interface{})(ptr) = f64
    76. return
    77. }
    78. iter.ReportError("DecodeNumber", err.Error())
    79. default:
    80. *(*interface{})(ptr) = iter.Read()
    81. }
    82. }
    83. // Decode attempts to convert the provided data into YAML or JSON, extract the stored schema kind, apply the provided default gvk, and then
    84. // load that data into an object matching the desired schema kind or the provided into.
    85. // If into is *runtime.Unknown, the raw data will be extracted and no decoding will be performed.
    86. // If into is not registered with the typer, then the object will be straight decoded using normal JSON/YAML unmarshalling.
    87. // 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.
    88. // If into is nil or data's gvk different from into's gvk, it will generate a new Object with ObjectCreater.New(gvk)
    89. // On success or most errors, the method will return the calculated schema kind.
    90. // The gvk calculate priority will be originalData > default gvk > into
    91. func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
    92. // 反序列化
    93. data := originalData
    94. if s.options.Yaml {
    95. altered, err := yaml.YAMLToJSON(data)
    96. if err != nil {
    97. return nil, nil, err
    98. }
    99. data = altered
    100. }
    101. // 获取gvk信息
    102. // 先反序列化获取gvk信息
    103. // 然后和默认gvk diff,返回实际的gvk信息
    104. actual, err := s.meta.Interpret(data)
    105. if err != nil {
    106. return nil, nil, err
    107. }
    108. if gvk != nil {
    109. *actual = gvkWithDefaults(*actual, *gvk)
    110. }
    111. if unk, ok := into.(*runtime.Unknown); ok && unk != nil {
    112. unk.Raw = originalData
    113. unk.ContentType = runtime.ContentTypeJSON
    114. unk.GetObjectKind().SetGroupVersionKind(*actual)
    115. return unk, actual, nil
    116. }
    117. if into != nil {
    118. // 动态客户端一般会用此obj(某些语言没有go对应的struct)
    119. _, isUnstructured := into.(runtime.Unstructured)
    120. types, _, err := s.typer.ObjectKinds(into)
    121. switch {
    122. case runtime.IsNotRegisteredError(err), isUnstructured:
    123. if err := caseSensitiveJsonIterator.Unmarshal(data, into); err != nil {
    124. return nil, actual, err
    125. }
    126. return into, actual, nil
    127. case err != nil:
    128. return nil, actual, err
    129. default:
    130. *actual = gvkWithDefaults(*actual, types[0])
    131. }
    132. }
    133. if len(actual.Kind) == 0 {
    134. return nil, actual, runtime.NewMissingKindErr(string(originalData))
    135. }
    136. if len(actual.Version) == 0 {
    137. return nil, actual, runtime.NewMissingVersionErr(string(originalData))
    138. }
    139. // use the target if necessary
    140. obj, err := runtime.UseOrCreateObject(s.typer, s.creater, *actual, into)
    141. if err != nil {
    142. return nil, actual, err
    143. }
    144. if err := caseSensitiveJsonIterator.Unmarshal(data, obj); err != nil {
    145. return nil, actual, err
    146. }
    147. // If the deserializer is non-strict, return successfully here.
    148. if !s.options.Strict {
    149. return obj, actual, nil
    150. }
    151. // In strict mode pass the data trough the YAMLToJSONStrict converter.
    152. // This is done to catch duplicate fields regardless of encoding (JSON or YAML). For JSON data,
    153. // the output would equal the input, unless there is a parsing error such as duplicate fields.
    154. // As we know this was successful in the non-strict case, the only error that may be returned here
    155. // is because of the newly-added strictness. hence we know we can return the typed strictDecoderError
    156. // the actual error is that the object contains duplicate fields.
    157. altered, err := yaml.YAMLToJSONStrict(originalData)
    158. if err != nil {
    159. return nil, actual, runtime.NewStrictDecodingError(err.Error(), string(originalData))
    160. }
    161. // As performance is not an issue for now for the strict deserializer (one has regardless to do
    162. // the unmarshal twice), we take the sanitized, altered data that is guaranteed to have no duplicated
    163. // fields, and unmarshal this into a copy of the already-populated obj. Any error that occurs here is
    164. // due to that a matching field doesn't exist in the object. hence we can return a typed strictDecoderError,
    165. // the actual error is that the object contains unknown field.
    166. strictObj := obj.DeepCopyObject()
    167. if err := strictCaseSensitiveJsonIterator.Unmarshal(altered, strictObj); err != nil {
    168. return nil, actual, runtime.NewStrictDecodingError(err.Error(), string(originalData))
    169. }
    170. // Always return the same object as the non-strict serializer to avoid any deviations.
    171. return obj, actual, nil
    172. }
    173. // Encode serializes the provided object to the given writer.
    174. func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error {
    175. if co, ok := obj.(runtime.CacheableObject); ok {
    176. return co.CacheEncode(s.Identifier(), s.doEncode, w)
    177. }
    178. return s.doEncode(obj, w)
    179. }
    180. func (s *Serializer) doEncode(obj runtime.Object, w io.Writer) error {
    181. if s.options.Yaml {
    182. jsonData, err := caseSensitiveJsonIterator.Marshal(obj)
    183. if err != nil {
    184. return err
    185. }
    186. data, err := yaml.JSONToYAML(jsonData)
    187. if err != nil {
    188. return err
    189. }
    190. _, err = w.Write(data)
    191. return err
    192. }
    193. if s.options.Pretty {
    194. data, err := caseSensitiveJsonIterator.MarshalIndent(obj, "", " ")
    195. if err != nil {
    196. return err
    197. }
    198. _, err = w.Write(data)
    199. return err
    200. }
    201. encoder := json.NewEncoder(w)
    202. return encoder.Encode(obj)
    203. }
    204. func (s *Serializer) Identifier() runtime.Identifier {
    205. return s.identifier
    206. }
    207. func (s *Serializer) RecognizesData(peek io.Reader) (ok, unknown bool, err error) {
    208. if s.options.Yaml {
    209. return false, true, nil
    210. }
    211. _, _, ok = utilyaml.GuessJSONStream(peek, 2048)
    212. return ok, false, nil
    213. }
    214. var Framer = jsonFramer{}
    215. type jsonFramer struct{}
    216. func (jsonFramer) NewFrameWriter(w io.Writer) io.Writer {
    217. return w
    218. }
    219. func (jsonFramer) NewFrameReader(r io.ReadCloser) io.ReadCloser {
    220. return framer.NewJSONFramedReader(r)
    221. }
    222. var YAMLFramer = yamlFramer{}
    223. type yamlFramer struct{}
    224. func (yamlFramer) NewFrameWriter(w io.Writer) io.Writer {
    225. return yamlFrameWriter{w}
    226. }
    227. func (yamlFramer) NewFrameReader(r io.ReadCloser) io.ReadCloser {
    228. return utilyaml.NewDocumentDecoder(r)
    229. }
    230. type yamlFrameWriter struct {
    231. w io.Writer
    232. }
    233. func (w yamlFrameWriter) Write(data []byte) (n int, err error) {
    234. if _, err := w.w.Write([]byte("---\n")); err != nil {
    235. return 0, err
    236. }
    237. return w.w.Write(data)
    238. }
    239. //---------------------------------------
    240. //---------------工具函数-----------------
    241. //---------------------------------------
    242. // CaseSensitiveJsonIterator returns a jsoniterator API that's configured to be
    243. // case-sensitive when unmarshalling, and otherwise compatible with
    244. // the encoding/json standard library.
    245. func CaseSensitiveJsonIterator() jsoniter.API {
    246. config := jsoniter.Config{
    247. EscapeHTML: true,
    248. SortMapKeys: true,
    249. ValidateJsonRawMessage: true,
    250. CaseSensitive: true,
    251. }.Froze()
    252. // Force jsoniter to decode number to interface{} via int64/float64, if possible.
    253. config.RegisterExtension(&customNumberExtension{})
    254. return config
    255. }
    256. // StrictCaseSensitiveJsonIterator returns a jsoniterator API that's configured to be
    257. // case-sensitive, but also disallows unknown fields when unmarshalling. It is compatible with
    258. // the encoding/json standard library.
    259. func StrictCaseSensitiveJsonIterator() jsoniter.API {
    260. config := jsoniter.Config{
    261. EscapeHTML: true,
    262. SortMapKeys: true,
    263. ValidateJsonRawMessage: true,
    264. CaseSensitive: true,
    265. DisallowUnknownFields: true,
    266. }.Froze()
    267. // Force jsoniter to decode number to interface{} via int64/float64, if possible.
    268. config.RegisterExtension(&customNumberExtension{})
    269. return config
    270. }
    271. func gvkWithDefaults(actual, defaultGVK schema.GroupVersionKind) schema.GroupVersionKind {
    272. if len(actual.Kind) == 0 {
    273. actual.Kind = defaultGVK.Kind
    274. }
    275. if len(actual.Version) == 0 && len(actual.Group) == 0 {
    276. actual.Group = defaultGVK.Group
    277. actual.Version = defaultGVK.Version
    278. }
    279. if len(actual.Version) == 0 && actual.Group == defaultGVK.Group {
    280. actual.Version = defaultGVK.Version
    281. }
    282. return actual
    283. }
    284. func identifier(options SerializerOptions) runtime.Identifier {
    285. result := map[string]string{
    286. "name": "json",
    287. "yaml": strconv.FormatBool(options.Yaml),
    288. "pretty": strconv.FormatBool(options.Pretty),
    289. }
    290. identifier, err := json.Marshal(result)
    291. if err != nil {
    292. klog.Fatalf("Failed marshaling identifier for json Serializer: %v", err)
    293. }
    294. return runtime.Identifier(identifier)
    295. }