@@ -18,8 +18,6 @@ import (
18
18
"encoding/json"
19
19
"fmt"
20
20
"math"
21
- "strconv"
22
- "strings"
23
21
)
24
22
25
23
// Object is used to allow integration with DeepCopy tool by replacing 'interface' generic type.
@@ -32,126 +30,68 @@ import (
32
30
// - Integer - holds int32 values, JSON marshal any number to float64 by default, during the marshaling process it is
33
31
// parsed to int32
34
32
// - raw - holds any not typed value, replaces the interface{} behavior.
33
+ //
34
+ // +kubebuilder:validation:Type=object
35
35
type Object struct {
36
- IObject `json:",inline"`
37
- }
38
-
39
- // IObject interface that can converted into one of the three subtypes
40
- type IObject interface {
41
- DeepCopyIObject () IObject
42
- }
43
-
44
- // raw generic subtype
45
- type raw struct {
46
- IObject interface {}
36
+ Type Type `json:",inline"`
37
+ IntVal int32 `json:",inline"`
38
+ StrVal string `json:",inline"`
39
+ RawValue json.RawMessage `json:",inline"`
47
40
}
48
41
49
- func (o raw ) DeepCopyIObject () IObject {
50
- return o
51
- }
42
+ type Type int64
52
43
53
- // Integer int32 type
54
- type Integer int
44
+ const (
45
+ Integer Type = iota
46
+ String
47
+ Raw
48
+ )
55
49
56
- func (m Integer ) DeepCopyIObject () IObject {
57
- return m
50
+ func FromInt (val int ) Object {
51
+ if val > math .MaxInt32 || val < math .MinInt32 {
52
+ fmt .Println (fmt .Errorf ("value: %d overflows int32" , val ))
53
+ }
54
+ return Object {Type : Integer , IntVal : int32 (val )}
58
55
}
59
56
60
- // String string type
61
- type String string
62
-
63
- func (m String ) DeepCopyIObject () IObject {
64
- return m
57
+ func FromString (val string ) Object {
58
+ return Object {Type : String , StrVal : val }
65
59
}
66
60
67
- // MarshalJSON marshal the given json object into the respective Object subtype.
68
- func (obj Object ) MarshalJSON () ([]byte , error ) {
69
- switch val := obj .IObject .(type ) {
70
- case String :
71
- return []byte (fmt .Sprintf (`%q` , val )), nil
72
- case Integer :
73
- return []byte (fmt .Sprintf (`%d` , val )), nil
74
- case raw :
75
- custom , err := json .Marshal (& struct {
76
- raw
77
- }{
78
- val ,
79
- })
80
- if err != nil {
81
- return nil , err
82
- }
83
-
84
- // remove the field name and the last '}' for marshalling purposes
85
- st := strings .Replace (string (custom ), "{\" IObject\" :" , "" , 1 )
86
- st = strings .TrimSuffix (st , "}" )
87
- return []byte (st ), nil
88
- default :
89
- return []byte (fmt .Sprintf ("%+v" , obj .IObject )), nil
61
+ func FromRaw (val interface {}) Object {
62
+ custom , err := json .Marshal (val )
63
+ if err != nil {
64
+ er := fmt .Errorf ("failed to parse value to Raw: %w" , err )
65
+ fmt .Println (er .Error ())
66
+ return Object {}
90
67
}
68
+ return Object {Type : Raw , RawValue : custom }
91
69
}
92
70
93
71
// UnmarshalJSON ...
94
72
func (obj * Object ) UnmarshalJSON (data []byte ) error {
95
- var test interface {}
96
- if err := json .Unmarshal (data , & test ); err != nil {
97
- return err
73
+ if data [0 ] == '"' {
74
+ obj .Type = String
75
+ return json .Unmarshal (data , & obj .StrVal )
76
+ } else if data [0 ] == '{' {
77
+ obj .Type = Raw
78
+ return json .Unmarshal (data , & obj .RawValue )
98
79
}
99
- switch val := test .(type ) {
100
- case string :
101
- var strVal String
102
- if err := json .Unmarshal (data , & strVal ); err != nil {
103
- return err
104
- }
105
- obj .IObject = strVal
106
- return nil
107
-
108
- case map [string ]interface {}:
109
- var cstVal raw
110
- if err := json .Unmarshal (data , & cstVal .IObject ); err != nil {
111
- return err
112
- }
113
- obj .IObject = cstVal
114
- return nil
115
-
116
- default :
117
- // json parses all not typed numbers as float64, let's enforce to int32
118
- if valInt , parseErr := strconv .Atoi (fmt .Sprint (val )); parseErr != nil {
119
- return fmt .Errorf ("falied to parse %d to int32: %w" , valInt , parseErr )
120
- } else {
121
- var intVal Integer
122
- if err := json .Unmarshal (data , & intVal ); err != nil {
123
- return err
124
- }
125
- obj .IObject = intVal
126
- return nil
127
- }
128
- }
129
- }
130
-
131
- // FromInt creates an Object with an int32 value.
132
- func FromInt (val int ) Object {
133
- if val > math .MaxInt32 || val < math .MinInt32 {
134
- panic (fmt .Errorf ("value: %d overflows int32" , val ))
135
- }
136
- return Object {Integer (int32 (val ))}
137
- }
138
-
139
- // FromString creates an Object with a string value.
140
- func FromString (val string ) Object {
141
- return Object {String (val )}
80
+ obj .Type = Integer
81
+ return json .Unmarshal (data , & obj .IntVal )
142
82
}
143
83
144
- // FromRaw creates an Object with untyped values.
145
- func FromRaw (val interface {}) Object {
146
- var rawVal Object
147
- data , err := json .Marshal (val )
148
- if err != nil {
149
- panic (err )
150
- }
151
- var cstVal raw
152
- if err := json .Unmarshal (data , & cstVal .IObject ); err != nil {
153
- panic (err )
84
+ // MarshalJSON marshal the given json object into the respective Object subtype.
85
+ func (obj Object ) MarshalJSON () ([]byte , error ) {
86
+ switch obj .Type {
87
+ case String :
88
+ return []byte (fmt .Sprintf (`%q` , obj .StrVal )), nil
89
+ case Integer :
90
+ return []byte (fmt .Sprintf (`%d` , obj .IntVal )), nil
91
+ case Raw :
92
+ val , _ := json .Marshal (obj .RawValue )
93
+ return val , nil
94
+ default :
95
+ return []byte (fmt .Sprintf ("%+v" , obj )), nil
154
96
}
155
- rawVal .IObject = cstVal
156
- return rawVal
157
97
}
0 commit comments