chore: support parsing any type with `fromYaml` (#2017)

Signed-off-by: Jakob Probst <git@jakobprobst.de>
This commit is contained in:
ProbstDJakob 2025-04-25 00:56:01 +02:00 committed by GitHub
parent c41f3e88d2
commit 0a31423005
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 102 additions and 34 deletions

View File

@ -19,7 +19,7 @@ func CastKeysToStrings(s any) (map[string]any, error) {
return nil, fmt.Errorf("unexpected type of key in map: expected string, got %T: value=%v, map=%v", typedK, typedK, src)
}
castedV, err := recursivelyStringifyMapKey(v)
castedV, err := RecursivelyStringifyMapKey(v)
if err != nil {
return nil, err
}
@ -28,7 +28,7 @@ func CastKeysToStrings(s any) (map[string]any, error) {
}
case map[string]any:
for k, v := range src {
castedV, err := recursivelyStringifyMapKey(v)
castedV, err := RecursivelyStringifyMapKey(v)
if err != nil {
return nil, err
}
@ -39,7 +39,7 @@ func CastKeysToStrings(s any) (map[string]any, error) {
return new, nil
}
func recursivelyStringifyMapKey(v any) (any, error) {
func RecursivelyStringifyMapKey(v any) (any, error) {
var castedV any
switch typedV := v.(type) {
case map[any]any, map[string]any:
@ -51,7 +51,7 @@ func recursivelyStringifyMapKey(v any) (any, error) {
case []any:
a := []any{}
for i := range typedV {
res, err := recursivelyStringifyMapKey(typedV[i])
res, err := RecursivelyStringifyMapKey(typedV[i])
if err != nil {
return nil, err
}

View File

@ -307,14 +307,14 @@ func ToYaml(v any) (string, error) {
return string(data), nil
}
func FromYaml(str string) (Values, error) {
m := map[string]any{}
func FromYaml(str string) (any, error) {
var m any
if err := yaml.Unmarshal([]byte(str), &m); err != nil {
return nil, fmt.Errorf("%s, offending yaml: %s", err, str)
}
m, err := maputil.CastKeysToStrings(m)
m, err := maputil.RecursivelyStringifyMapKey(m)
if err != nil {
return nil, fmt.Errorf("%s, offending yaml: %s", err, str)
}

View File

@ -200,7 +200,88 @@ func TestToYaml(t *testing.T) {
require.Equal(t, expected, actual)
}
func testFromYaml(t *testing.T, goccyGoYaml bool, expected Values) {
func testFromYamlObject(t *testing.T) {
raw := `foo:
bar: BAR
`
actual, err := FromYaml(raw)
require.NoError(t, err)
require.Equal(
t,
map[string]any{
"foo": map[string]any{
"bar": "BAR",
},
},
actual,
)
}
func testFromYamlArray(t *testing.T) {
raw := `- foo
- bar: BAR
`
actual, err := FromYaml(raw)
require.NoError(t, err)
require.Equal(
t,
[]any{
"foo",
map[string]any{
"bar": "BAR",
},
},
actual,
)
}
func testFromYamlString(t *testing.T) {
raw := `foo
`
actual, err := FromYaml(raw)
require.NoError(t, err)
require.Equal(t, "foo", actual)
}
func testFromYamlNumber(t *testing.T) {
raw := `1234
`
actual, err := FromYaml(raw)
require.NoError(t, err)
switch a := actual.(type) {
case int:
require.Equal(t, 1234, a)
case uint64:
require.Equal(t, uint64(1234), a)
default:
t.Errorf("unexpected type: %T", a)
}
}
func testFromYamlBoolean(t *testing.T) {
raw := `true
`
actual, err := FromYaml(raw)
require.NoError(t, err)
require.Equal(t, true, actual)
}
func testFromYamlNull(t *testing.T) {
raw := `null
`
actual, err := FromYaml(raw)
require.NoError(t, err)
require.Equal(t, nil, actual)
}
func testFromYaml(t *testing.T, goccyGoYaml bool) {
t.Helper()
v := runtime.GoccyGoYaml
@ -209,39 +290,26 @@ func testFromYaml(t *testing.T, goccyGoYaml bool, expected Values) {
runtime.GoccyGoYaml = v
})
raw := `foo:
bar: BAR
`
actual, err := FromYaml(raw)
require.NoError(t, err)
require.Equal(t, expected, actual)
t.Run("test unmarshalling object", testFromYamlObject)
t.Run("test unmarshalling array", testFromYamlArray)
t.Run("test unmarshalling string", testFromYamlString)
t.Run("test unmarshalling number", testFromYamlNumber)
t.Run("test unmarshalling boolean", testFromYamlBoolean)
t.Run("test unmarshalling null", testFromYamlNull)
}
func TestFromYaml(t *testing.T) {
t.Run("with goccy/go-yaml", func(t *testing.T) {
testFromYaml(
t,
true,
// nolint: unconvert
Values(map[string]any{
"foo": map[string]any{
"bar": "BAR",
},
}),
)
testFromYaml(t, true)
})
t.Run("with gopkg.in/yaml.v2", func(t *testing.T) {
testFromYaml(
t,
false,
// nolint: unconvert
Values(map[string]any{
"foo": map[string]any{
"bar": "BAR",
},
}),
)
testFromYaml(t, false)
})
}