// Copyright 2022 schukai GmbH // SPDX-License-Identifier: AGPL-3.0 package pathfinder import ( "reflect" "strconv" "strings" ) // This function returns the value of a field in a struct, given a path to the field. func GetValue[D any](obj D, keyWithDots string) (any, error) { keySlice := strings.Split(keyWithDots, ".") v := reflect.ValueOf(obj) for _, key := range keySlice[0:len(keySlice)] { switch v.Kind() { case reflect.Ptr, reflect.Slice, reflect.Array, reflect.Interface: v = v.Elem() } switch v.Kind() { case reflect.Map: v = v.MapIndex(reflect.ValueOf(key)) if !v.IsValid() { return nil, newInvalidPathError(keyWithDots) } case reflect.Slice, reflect.Array: index, err := strconv.Atoi(key) if err != nil { return nil, newInvalidPathError(keyWithDots) } v = v.Index(index) case reflect.Struct: v = v.FieldByName(key) if !v.IsValid() { return nil, newInvalidPathError(keyWithDots) } default: return nil, newInvalidPathError(keyWithDots) } } if v.Kind() == reflect.Invalid { return nil, newInvalidPathError(keyWithDots) } for v.Kind() == reflect.Ptr { v = v.Elem() } return v.Interface(), nil }