Skip to content

Commit acbe5a4

Browse files
authored
Fix unmarshaling empty strings (#7)
Signed-off-by: Kimmo Lehto <[email protected]>
1 parent e2b282d commit acbe5a4

File tree

2 files changed

+60
-3
lines changed

2 files changed

+60
-3
lines changed

version.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,14 @@ func pair(a, b *Version) Collection {
2222

2323
// String returns a v-prefixed string representation of the k0s version
2424
func (v *Version) String() string {
25-
return fmt.Sprintf("v%s", v.Version.String())
25+
if v == nil {
26+
return ""
27+
}
28+
plain := strings.TrimPrefix(v.Version.String(), "v")
29+
if plain == "" {
30+
return ""
31+
}
32+
return fmt.Sprintf("v%s", plain)
2633
}
2734

2835
func (v *Version) urlString() string {
@@ -112,11 +119,19 @@ func (v *Version) Compare(b *Version) int {
112119

113120
// MarshalJSON implements the json.Marshaler interface.
114121
func (v *Version) MarshalJSON() ([]byte, error) {
122+
if v == nil {
123+
return []byte("null"), nil
124+
}
125+
115126
return []byte(fmt.Sprintf("\"%s\"", v.String())), nil
116127
}
117128

118129
// MarshalYAML implements the yaml.Marshaler interface.
119130
func (v *Version) MarshalYAML() (interface{}, error) {
131+
if v == nil {
132+
return nil, nil
133+
}
134+
120135
return v.String(), nil
121136
}
122137

@@ -125,6 +140,9 @@ func (v *Version) unmarshal(f func(interface{}) error) error {
125140
if err := f(&s); err != nil {
126141
return fmt.Errorf("failed to decode input: %w", err)
127142
}
143+
if s == "" {
144+
return nil
145+
}
128146
newV, err := NewVersion(s)
129147
if err != nil {
130148
return fmt.Errorf("failed to unmarshal version: %w", err)
@@ -141,12 +159,21 @@ func (v *Version) UnmarshalYAML(f func(interface{}) error) error {
141159
// UnmarshalJSON implements the json.Unmarshaler interface.
142160
func (v *Version) UnmarshalJSON(b []byte) error {
143161
s := strings.TrimSpace(strings.Trim(string(b), "\""))
162+
if s == "" || s == "null" {
163+
// go doesn't allow to set nil to a non-pointer struct field, so the result
164+
// is going to be an empty struct
165+
return nil
166+
}
144167
return v.unmarshal(func(i interface{}) error {
145168
*(i.(*string)) = s
146169
return nil
147170
})
148171
}
149172

173+
func (v *Version) IsZero() bool {
174+
return v == nil || v.String() == ""
175+
}
176+
150177
// Satisfies returns true if the version satisfies the supplied constraint
151178
func (v *Version) Satisfies(constraint Constraints) bool {
152179
return constraint.Check(v)

version_test.go

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,25 @@ func TestMarshalling(t *testing.T) {
7676
assert.NoError(t, err)
7777
assert.Equal(t, "v1.0.0+k0s.0", yamlData)
7878
})
79+
80+
t.Run("JSON with nil", func(t *testing.T) {
81+
jsonData, err := json.Marshal(nil)
82+
assert.NoError(t, err)
83+
assert.Equal(t, `null`, string(jsonData))
84+
})
85+
86+
t.Run("YAML", func(t *testing.T) {
87+
var nilVersion *Version
88+
yamlData, err := nilVersion.MarshalYAML()
89+
assert.NoError(t, err)
90+
assert.Nil(t, yamlData)
91+
})
7992
}
8093

8194
func TestUnmarshalling(t *testing.T) {
8295
t.Run("JSON", func(t *testing.T) {
83-
var v Version
84-
err := json.Unmarshal([]byte(`"v1.0.0+k0s.1"`), &v)
96+
v := &Version{}
97+
err := json.Unmarshal([]byte(`"v1.0.0+k0s.1"`), v)
8598
assert.NoError(t, err)
8699
assert.Equal(t, "v1.0.0+k0s.1", v.String())
87100
})
@@ -95,6 +108,23 @@ func TestUnmarshalling(t *testing.T) {
95108
assert.NoError(t, err)
96109
assert.Equal(t, "v1.0.0+k0s.1", v.String())
97110
})
111+
112+
t.Run("JSON with null", func(t *testing.T) {
113+
v := &Version{}
114+
err := json.Unmarshal([]byte(`null`), v)
115+
assert.NoError(t, err)
116+
assert.True(t, v.IsZero())
117+
})
118+
119+
t.Run("YAML with empty", func(t *testing.T) {
120+
v := &Version{}
121+
err := v.UnmarshalYAML(func(i interface{}) error {
122+
*(i.(*string)) = ""
123+
return nil
124+
})
125+
assert.NoError(t, err)
126+
assert.Nil(t, nil, v)
127+
})
98128
}
99129

100130
func TestFailingUnmarshalling(t *testing.T) {

0 commit comments

Comments
 (0)