1
16
17 package json
18
19 import (
20 "encoding/json"
21 "io"
22 "strconv"
23
24 kjson "sigs.k8s.io/json"
25 "sigs.k8s.io/yaml"
26
27 "k8s.io/apimachinery/pkg/runtime"
28 "k8s.io/apimachinery/pkg/runtime/schema"
29 "k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
30 "k8s.io/apimachinery/pkg/util/framer"
31 utilyaml "k8s.io/apimachinery/pkg/util/yaml"
32 "k8s.io/klog/v2"
33 )
34
35
36
37
38 func NewSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper, pretty bool) *Serializer {
39 return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{false, pretty, false})
40 }
41
42
43
44
45
46 func NewYAMLSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper) *Serializer {
47 return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{true, false, false})
48 }
49
50
51
52
53 func NewSerializerWithOptions(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper, options SerializerOptions) *Serializer {
54 return &Serializer{
55 meta: meta,
56 creater: creater,
57 typer: typer,
58 options: options,
59 identifier: identifier(options),
60 }
61 }
62
63
64 func identifier(options SerializerOptions) runtime.Identifier {
65 result := map[string]string{
66 "name": "json",
67 "yaml": strconv.FormatBool(options.Yaml),
68 "pretty": strconv.FormatBool(options.Pretty),
69 "strict": strconv.FormatBool(options.Strict),
70 }
71 identifier, err := json.Marshal(result)
72 if err != nil {
73 klog.Fatalf("Failed marshaling identifier for json Serializer: %v", err)
74 }
75 return runtime.Identifier(identifier)
76 }
77
78
79
80
81
82
83 type SerializerOptions struct {
84
85
86
87 Yaml bool
88
89
90
91 Pretty bool
92
93
94
95 Strict bool
96 }
97
98
99 type Serializer struct {
100 meta MetaFactory
101 options SerializerOptions
102 creater runtime.ObjectCreater
103 typer runtime.ObjectTyper
104
105 identifier runtime.Identifier
106 }
107
108
109 var _ runtime.Serializer = &Serializer{}
110 var _ recognizer.RecognizingDecoder = &Serializer{}
111
112
113 func gvkWithDefaults(actual, defaultGVK schema.GroupVersionKind) schema.GroupVersionKind {
114 if len(actual.Kind) == 0 {
115 actual.Kind = defaultGVK.Kind
116 }
117 if len(actual.Version) == 0 && len(actual.Group) == 0 {
118 actual.Group = defaultGVK.Group
119 actual.Version = defaultGVK.Version
120 }
121 if len(actual.Version) == 0 && actual.Group == defaultGVK.Group {
122 actual.Version = defaultGVK.Version
123 }
124 return actual
125 }
126
127
128
129
130
131
132
133
134
135 func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
136 data := originalData
137 if s.options.Yaml {
138 altered, err := yaml.YAMLToJSON(data)
139 if err != nil {
140 return nil, nil, err
141 }
142 data = altered
143 }
144
145 actual, err := s.meta.Interpret(data)
146 if err != nil {
147 return nil, nil, err
148 }
149
150 if gvk != nil {
151 *actual = gvkWithDefaults(*actual, *gvk)
152 }
153
154 if unk, ok := into.(*runtime.Unknown); ok && unk != nil {
155 unk.Raw = originalData
156 unk.ContentType = runtime.ContentTypeJSON
157 unk.GetObjectKind().SetGroupVersionKind(*actual)
158 return unk, actual, nil
159 }
160
161 if into != nil {
162 _, isUnstructured := into.(runtime.Unstructured)
163 types, _, err := s.typer.ObjectKinds(into)
164 switch {
165 case runtime.IsNotRegisteredError(err), isUnstructured:
166 strictErrs, err := s.unmarshal(into, data, originalData)
167 if err != nil {
168 return nil, actual, err
169 }
170
171
172
173
174 if isUnstructured {
175 *actual = into.GetObjectKind().GroupVersionKind()
176 if len(actual.Kind) == 0 {
177 return nil, actual, runtime.NewMissingKindErr(string(originalData))
178 }
179
180 }
181
182 if len(strictErrs) > 0 {
183 return into, actual, runtime.NewStrictDecodingError(strictErrs)
184 }
185 return into, actual, nil
186 case err != nil:
187 return nil, actual, err
188 default:
189 *actual = gvkWithDefaults(*actual, types[0])
190 }
191 }
192
193 if len(actual.Kind) == 0 {
194 return nil, actual, runtime.NewMissingKindErr(string(originalData))
195 }
196 if len(actual.Version) == 0 {
197 return nil, actual, runtime.NewMissingVersionErr(string(originalData))
198 }
199
200
201 obj, err := runtime.UseOrCreateObject(s.typer, s.creater, *actual, into)
202 if err != nil {
203 return nil, actual, err
204 }
205
206 strictErrs, err := s.unmarshal(obj, data, originalData)
207 if err != nil {
208 return nil, actual, err
209 } else if len(strictErrs) > 0 {
210 return obj, actual, runtime.NewStrictDecodingError(strictErrs)
211 }
212 return obj, actual, nil
213 }
214
215
216 func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error {
217 if co, ok := obj.(runtime.CacheableObject); ok {
218 return co.CacheEncode(s.Identifier(), s.doEncode, w)
219 }
220 return s.doEncode(obj, w)
221 }
222
223 func (s *Serializer) doEncode(obj runtime.Object, w io.Writer) error {
224 if s.options.Yaml {
225 json, err := json.Marshal(obj)
226 if err != nil {
227 return err
228 }
229 data, err := yaml.JSONToYAML(json)
230 if err != nil {
231 return err
232 }
233 _, err = w.Write(data)
234 return err
235 }
236
237 if s.options.Pretty {
238 data, err := json.MarshalIndent(obj, "", " ")
239 if err != nil {
240 return err
241 }
242 _, err = w.Write(data)
243 return err
244 }
245 encoder := json.NewEncoder(w)
246 return encoder.Encode(obj)
247 }
248
249
250
251 func (s *Serializer) IsStrict() bool {
252 return s.options.Strict
253 }
254
255 func (s *Serializer) unmarshal(into runtime.Object, data, originalData []byte) (strictErrs []error, err error) {
256
257 if !s.options.Strict {
258 if err := kjson.UnmarshalCaseSensitivePreserveInts(data, into); err != nil {
259 return nil, err
260 }
261 return nil, nil
262 }
263
264 if s.options.Yaml {
265
266
267
268 _, err := yaml.YAMLToJSONStrict(originalData)
269 if err != nil {
270 strictErrs = append(strictErrs, err)
271 }
272 }
273
274 var strictJSONErrs []error
275 if u, isUnstructured := into.(runtime.Unstructured); isUnstructured {
276
277
278
279 m := map[string]interface{}{}
280 strictJSONErrs, err = kjson.UnmarshalStrict(data, &m)
281 u.SetUnstructuredContent(m)
282 } else {
283 strictJSONErrs, err = kjson.UnmarshalStrict(data, into)
284 }
285 if err != nil {
286
287 return nil, err
288 }
289 strictErrs = append(strictErrs, strictJSONErrs...)
290 return strictErrs, nil
291 }
292
293
294 func (s *Serializer) Identifier() runtime.Identifier {
295 return s.identifier
296 }
297
298
299 func (s *Serializer) RecognizesData(data []byte) (ok, unknown bool, err error) {
300 if s.options.Yaml {
301
302 return false, true, nil
303 }
304 return utilyaml.IsJSONBuffer(data), false, nil
305 }
306
307
308 var Framer = jsonFramer{}
309
310 type jsonFramer struct{}
311
312
313 func (jsonFramer) NewFrameWriter(w io.Writer) io.Writer {
314
315 return w
316 }
317
318
319 func (jsonFramer) NewFrameReader(r io.ReadCloser) io.ReadCloser {
320
321 return framer.NewJSONFramedReader(r)
322 }
323
324
325 var YAMLFramer = yamlFramer{}
326
327 type yamlFramer struct{}
328
329
330 func (yamlFramer) NewFrameWriter(w io.Writer) io.Writer {
331 return yamlFrameWriter{w}
332 }
333
334
335 func (yamlFramer) NewFrameReader(r io.ReadCloser) io.ReadCloser {
336
337 return utilyaml.NewDocumentDecoder(r)
338 }
339
340 type yamlFrameWriter struct {
341 w io.Writer
342 }
343
344
345
346 func (w yamlFrameWriter) Write(data []byte) (n int, err error) {
347 if _, err := w.w.Write([]byte("---\n")); err != nil {
348 return 0, err
349 }
350 return w.w.Write(data)
351 }
352
View as plain text