Skip to content

Commit

Permalink
lxc/utils: Support parsing of anonymous nested structs
Browse files Browse the repository at this point in the history
Signed-off-by: Gabriel Mougard <[email protected]>
  • Loading branch information
gabrielmougard committed Jul 24, 2023
1 parent fa2ec65 commit 6d7b7ef
Showing 1 changed file with 34 additions and 8 deletions.
42 changes: 34 additions & 8 deletions lxc/utils_properties.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,27 @@ func stringToFloatHookFunc() mapstructure.DecodeHookFunc {
// getFieldByJsonTag gets the value of a struct field by its JSON tag.
func getFieldByJsonTag(obj any, tag string) (any, error) {
var res any
ok := false
v := reflect.ValueOf(obj).Elem()
v := reflect.ValueOf(obj)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}

if v.Kind() != reflect.Struct {
return nil, fmt.Errorf("Expected a struct, got a %v", v.Kind())
}

ok, res := getFromStruct(v, tag)
if !ok {
return nil, fmt.Errorf("The property with tag %q does not exist", tag)
}

return res, nil
}

// getFromStruct scans a struct for a field with the given JSON tag, including fields of inline structs.
func getFromStruct(v reflect.Value, tag string) (bool, any) {
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
jsonTag := v.Type().Field(i).Tag.Get("json")

// Ignore any options that might be specified after a comma in the tag.
Expand All @@ -98,16 +116,24 @@ func getFieldByJsonTag(obj any, tag string) (any, error) {
}

if strings.EqualFold(jsonTag, tag) {
res = v.Field(i).Interface()
ok = true
return true, field.Interface()
}
}

if !ok {
return nil, fmt.Errorf("The property with tag %q does not exist", tag)
if v.Type().Field(i).Anonymous {
if field.Kind() == reflect.Ptr {
field = field.Elem()
}

if field.Kind() == reflect.Struct {
ok, res := getFromStruct(field, tag)
if ok {
return ok, res
}
}
}
}

return res, nil
return false, nil
}

// setFieldByJsonTag sets the value of a struct field by its JSON tag.
Expand Down

0 comments on commit 6d7b7ef

Please sign in to comment.