Skip to content
Snippets Groups Projects
get.go 1.17 KiB
// 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

}