add support for map

to CEL mutation library.
This commit is contained in:
Jiahui Feng 2024-02-27 13:55:08 -08:00
parent 3852d1c0c1
commit dc4c92f5a5
2 changed files with 36 additions and 4 deletions

View File

@ -55,7 +55,11 @@ func (v *ObjectVal) ConvertToNative(typeDesc reflect.Type) (any, error) {
}
result = make(map[string]any, len(v.fields))
for k, v := range v.fields {
result[k] = convertField(v)
converted, err := convertField(v)
if err != nil {
return nil, fmt.Errorf("fail to convert field %q: %w", k, err)
}
result[k] = converted
}
return result, nil
}
@ -104,8 +108,12 @@ func (v *ObjectVal) IsZeroValue() bool {
// convertField converts a referred ref.Val to its expected type.
// For objects, the expected type is map[string]any
// For lists, the expected type is []any
// For maps, the expected type is map[string]any
// For anything else, it is converted via value.Value()
func convertField(value ref.Val) any {
//
// It will return an error if the request type is a map but the key
// is not a string.
func convertField(value ref.Val) (any, error) {
// special handling for lists, where the elements are converted with Value() instead of ConvertToNative
// to allow them to become native value of any type.
if listOfVal, ok := value.Value().([]ref.Val); ok {
@ -113,7 +121,20 @@ func convertField(value ref.Val) any {
for _, v := range listOfVal {
result = append(result, v.Value())
}
return result
return result, nil
}
return value.Value()
// unstructured maps, as seen in annotations
// map keys must be strings
if mapOfVal, ok := value.Value().(map[ref.Val]ref.Val); ok {
result := make(map[string]any)
for k, v := range mapOfVal {
stringKey, ok := k.Value().(string)
if !ok {
return nil, fmt.Errorf("map key %q is of type %t, not string", k, k)
}
result[stringKey] = v.Value()
}
return result, nil
}
return value.Value(), nil
}

View File

@ -94,6 +94,17 @@ func TestTypeProvider(t *testing.T) {
"intList": []any{int64(1), int64(2), int64(3)},
},
},
{
name: "map string-to-string",
expression: `Object{
annotations: {"foo": "bar"}
}`,
expectedValue: map[string]any{
"annotations": map[string]any{
"foo": "bar",
},
},
},
{
name: "field access",
expression: `Object{