15
15
package model
16
16
17
17
import (
18
+ "bytes"
18
19
"encoding/json"
19
20
"fmt"
20
21
"math"
22
+ "strconv"
23
+ )
24
+
25
+ type Type int8
26
+
27
+ const (
28
+ Null Type = iota
29
+ String
30
+ Int
31
+ Float
32
+ Map
33
+ Slice
34
+ Bool
21
35
)
22
36
23
37
// Object is used to allow integration with DeepCopy tool by replacing 'interface' generic type.
@@ -29,80 +43,167 @@ import (
29
43
// - String - holds string values
30
44
// - Integer - holds int32 values, JSON marshal any number to float64 by default, during the marshaling process it is
31
45
// parsed to int32
32
- // - raw - holds any not typed value, replaces the interface{} behavior.
33
46
//
34
47
// +kubebuilder:validation:Type=object
35
48
type Object struct {
36
- Type Type `json:"type,inline"`
37
- IntVal int32 `json:"intVal,inline"`
38
- StrVal string `json:"strVal,inline"`
39
- RawValue json.RawMessage `json:"rawValue,inline"`
40
- BoolValue bool `json:"boolValue,inline"`
49
+ Type Type `json:"type,inline"`
50
+ StringValue string `json:"strVal,inline"`
51
+ IntValue int32 `json:"intVal,inline"`
52
+ FloatValue float64
53
+ MapValue map [string ]Object
54
+ SliceValue []Object
55
+ BoolValue bool `json:"boolValue,inline"`
41
56
}
42
57
43
- type Type int64
58
+ // UnmarshalJSON implements json.Unmarshaler
59
+ func (obj * Object ) UnmarshalJSON (data []byte ) error {
60
+ data = bytes .TrimSpace (data )
44
61
45
- const (
46
- Integer Type = iota
47
- String
48
- Raw
49
- Boolean
50
- )
62
+ if data [0 ] == '"' {
63
+ obj .Type = String
64
+ return json .Unmarshal (data , & obj .StringValue )
65
+ } else if data [0 ] == 't' || data [0 ] == 'f' {
66
+ obj .Type = Bool
67
+ return json .Unmarshal (data , & obj .BoolValue )
68
+ } else if data [0 ] == 'n' {
69
+ obj .Type = Null
70
+ return nil
71
+ } else if data [0 ] == '{' {
72
+ obj .Type = Map
73
+ return json .Unmarshal (data , & obj .MapValue )
74
+ } else if data [0 ] == '[' {
75
+ obj .Type = Slice
76
+ return json .Unmarshal (data , & obj .SliceValue )
77
+ }
78
+
79
+ number := string (data )
80
+ intValue , err := strconv .ParseInt (number , 10 , 32 )
81
+ if err == nil {
82
+ obj .Type = Int
83
+ obj .IntValue = int32 (intValue )
84
+ return nil
85
+ }
86
+
87
+ floatValue , err := strconv .ParseFloat (number , 64 )
88
+ if err == nil {
89
+ obj .Type = Float
90
+ obj .FloatValue = floatValue
91
+ return nil
92
+ }
93
+
94
+ return fmt .Errorf ("json invalid number %q" , number )
95
+ }
96
+
97
+ // MarshalJSON marshal the given json object into the respective Object subtype.
98
+ func (obj Object ) MarshalJSON () ([]byte , error ) {
99
+ switch obj .Type {
100
+ case String :
101
+ return []byte (fmt .Sprintf (`%q` , obj .StringValue )), nil
102
+ case Int :
103
+ return []byte (fmt .Sprintf (`%d` , obj .IntValue )), nil
104
+ case Float :
105
+ return []byte (fmt .Sprintf (`%f` , obj .FloatValue )), nil
106
+ case Map :
107
+ return json .Marshal (obj .MapValue )
108
+ case Slice :
109
+ return json .Marshal (obj .SliceValue )
110
+ case Bool :
111
+ return []byte (fmt .Sprintf (`%t` , obj .BoolValue )), nil
112
+ case Null :
113
+ return []byte ("null" ), nil
114
+ default :
115
+ panic ("object invalid type" )
116
+ }
117
+ }
118
+
119
+ func FromString (val string ) Object {
120
+ return Object {Type : String , StringValue : val }
121
+ }
51
122
52
123
func FromInt (val int ) Object {
53
124
if val > math .MaxInt32 || val < math .MinInt32 {
54
125
fmt .Println (fmt .Errorf ("value: %d overflows int32" , val ))
55
126
}
56
- return Object {Type : Integer , IntVal : int32 (val )}
127
+ return Object {Type : Int , IntValue : int32 (val )}
57
128
}
58
129
59
- func FromString (val string ) Object {
60
- return Object {Type : String , StrVal : val }
130
+ func FromFloat (val float64 ) Object {
131
+ if val > math .MaxFloat64 || val < - math .MaxFloat64 {
132
+ fmt .Println (fmt .Errorf ("value: %f overflows float64" , val ))
133
+ }
134
+ return Object {Type : Float , FloatValue : float64 (val )}
61
135
}
62
136
63
- func FromBool (val bool ) Object {
64
- return Object {Type : Boolean , BoolValue : val }
137
+ func FromMap (mapValue map [string ]any ) Object {
138
+ mapValueObject := make (map [string ]Object , len (mapValue ))
139
+ for key , value := range mapValue {
140
+ mapValueObject [key ] = FromInterface (value )
141
+ }
142
+ return Object {Type : Map , MapValue : mapValueObject }
65
143
}
66
144
67
- func FromRaw (val interface {}) Object {
68
- custom , err := json .Marshal (val )
69
- if err != nil {
70
- er := fmt .Errorf ("failed to parse value to Raw: %w" , err )
71
- fmt .Println (er .Error ())
72
- return Object {}
145
+ func FromSlice (sliceValue []any ) Object {
146
+ sliceValueObject := make ([]Object , len (sliceValue ))
147
+ for key , value := range sliceValue {
148
+ sliceValueObject [key ] = FromInterface (value )
73
149
}
74
- return Object {Type : Raw , RawValue : custom }
150
+ return Object {Type : Slice , SliceValue : sliceValueObject }
75
151
}
76
152
77
- // UnmarshalJSON implements json.Unmarshaler
78
- func (obj * Object ) UnmarshalJSON (data []byte ) error {
79
- if data [0 ] == '"' {
80
- obj .Type = String
81
- return json .Unmarshal (data , & obj .StrVal )
82
- } else if data [0 ] == 't' || data [0 ] == 'f' {
83
- obj .Type = Boolean
84
- return json .Unmarshal (data , & obj .BoolValue )
85
- } else if data [0 ] == '{' {
86
- obj .Type = Raw
87
- return json .Unmarshal (data , & obj .RawValue )
153
+ func FromBool (val bool ) Object {
154
+ return Object {Type : Bool , BoolValue : val }
155
+ }
156
+
157
+ func FromNull () Object {
158
+ return Object {Type : Null }
159
+ }
160
+
161
+ func FromInterface (value any ) Object {
162
+ switch v := value .(type ) {
163
+ case string :
164
+ return FromString (v )
165
+ case int :
166
+ return FromInt (v )
167
+ case int32 :
168
+ return FromInt (int (v ))
169
+ case float64 :
170
+ return FromFloat (v )
171
+ case map [string ]any :
172
+ return FromMap (v )
173
+ case []any :
174
+ return FromSlice (v )
175
+ case bool :
176
+ return FromBool (v )
177
+ case nil :
178
+ return FromNull ()
88
179
}
89
- obj .Type = Integer
90
- return json .Unmarshal (data , & obj .IntVal )
180
+ panic ("invalid type" )
91
181
}
92
182
93
- // MarshalJSON marshal the given json object into the respective Object subtype.
94
- func (obj Object ) MarshalJSON () ([]byte , error ) {
95
- switch obj .Type {
183
+ func ToInterface (object Object ) any {
184
+ switch object .Type {
96
185
case String :
97
- return []byte (fmt .Sprintf (`%q` , obj .StrVal )), nil
98
- case Boolean :
99
- return []byte (fmt .Sprintf (`%t` , obj .BoolValue )), nil
100
- case Integer :
101
- return []byte (fmt .Sprintf (`%d` , obj .IntVal )), nil
102
- case Raw :
103
- val , _ := json .Marshal (obj .RawValue )
104
- return val , nil
105
- default :
106
- return []byte (fmt .Sprintf ("%+v" , obj )), nil
186
+ return object .StringValue
187
+ case Int :
188
+ return object .IntValue
189
+ case Float :
190
+ return object .FloatValue
191
+ case Map :
192
+ mapInterface := make (map [string ]any , len (object .MapValue ))
193
+ for key , value := range object .MapValue {
194
+ mapInterface [key ] = ToInterface (value )
195
+ }
196
+ return mapInterface
197
+ case Slice :
198
+ sliceInterface := make ([]any , len (object .SliceValue ))
199
+ for key , value := range object .SliceValue {
200
+ sliceInterface [key ] = ToInterface (value )
201
+ }
202
+ return sliceInterface
203
+ case Bool :
204
+ return object .BoolValue
205
+ case Null :
206
+ return nil
107
207
}
208
+ panic ("invalid type" )
108
209
}
0 commit comments