forked from rook/rook
add rgw shared pools rados ns to topics_pool, account_pool, and group_pool Signed-off-by: Artem Torubarov <artem.torubarov@clyso.com>
125 lines
3.5 KiB
Go
125 lines
3.5 KiB
Go
package object
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// getObjProperty - helper function to manipulate JSON Objects.
|
|
// returns nested property of json object.
|
|
// Example:
|
|
//
|
|
// obj = {"a":{"b":"foo"}}
|
|
// // will return "foo"
|
|
// getObjProperty(obj,"a","b")
|
|
func getObjProperty[T string | map[string]interface{} | []interface{}](obj map[string]interface{}, path ...string) (T, error) {
|
|
var res T
|
|
if len(path) == 0 {
|
|
return res, fmt.Errorf("json property path is empty")
|
|
}
|
|
|
|
for i, p := range path {
|
|
val, ok := obj[p]
|
|
if !ok {
|
|
return res, fmt.Errorf("json property %q not found", strings.Join(path[:i+1], "."))
|
|
}
|
|
last := i == len(path)-1
|
|
if last {
|
|
// last path segment: get result
|
|
res, ok = val.(T)
|
|
if !ok {
|
|
return res, fmt.Errorf("json property %q is not a %T, got %+v", strings.Join(path, "."), res, val)
|
|
}
|
|
return res, nil
|
|
}
|
|
// walk to the next obj in the path
|
|
obj, ok = val.(map[string]interface{})
|
|
if !ok {
|
|
return res, fmt.Errorf("json property %q is not an object, got %+v", strings.Join(path[:i+1], "."), val)
|
|
}
|
|
}
|
|
// not reachable
|
|
return res, fmt.Errorf("json property %q not found", strings.Join(path, "."))
|
|
}
|
|
|
|
// updateObjProperty - helper function to manipulate JSON Objects.
|
|
// sets new value to json object nested field only if it is already exists in json and returns previous value.
|
|
func updateObjProperty[T string | []string | map[string]interface{} | []interface{}](obj map[string]interface{}, val T, path ...string) (T, error) {
|
|
var prev T
|
|
if len(path) == 0 {
|
|
return prev, fmt.Errorf("json property path is empty")
|
|
}
|
|
for i, p := range path {
|
|
last := i == len(path)-1
|
|
if last {
|
|
// last path segment: set result and return prev value
|
|
prevVal, ok := obj[p]
|
|
if !ok {
|
|
// not exists:
|
|
return prev, fmt.Errorf("json property %q not exists", strings.Join(path, "."))
|
|
}
|
|
if ok {
|
|
prevRes, ok := prevVal.(T)
|
|
if ok {
|
|
prev = prevRes
|
|
} else {
|
|
// in go json all arrays are []interface{}, extra conversion for typed arrays (e.g. []string) needed:
|
|
p := new(T)
|
|
if castJson(prevVal, p) {
|
|
prev = *p
|
|
}
|
|
}
|
|
}
|
|
obj[p] = val
|
|
return prev, nil
|
|
}
|
|
// walk to the next obj in the path
|
|
next, ok := obj[p]
|
|
if !ok {
|
|
return prev, fmt.Errorf("json property %q is not found", strings.Join(path[:i+1], "."))
|
|
}
|
|
obj, ok = next.(map[string]interface{})
|
|
if !ok {
|
|
return prev, fmt.Errorf("json property %q is not an object, got %+v", strings.Join(path[:i+1], "."), next)
|
|
}
|
|
}
|
|
// not reachable
|
|
return prev, fmt.Errorf("json property %q not found", strings.Join(path, "."))
|
|
}
|
|
|
|
// castJson - helper function to manipulate JSON Objects.
|
|
// Tries to cast any type to any type by converting to JSON and back.
|
|
// Returns true on success.
|
|
func castJson(in, out interface{}) bool {
|
|
bytes, err := json.Marshal(in)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
err = json.Unmarshal(bytes, out)
|
|
return err == nil
|
|
}
|
|
|
|
// toObj - helper function to manipulate JSON Objects.
|
|
// Casts any go struct to map representing JSON object.
|
|
func toObj(val interface{}) (map[string]interface{}, error) {
|
|
bytes, err := json.Marshal(val)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
obj := map[string]interface{}{}
|
|
return obj, json.Unmarshal(bytes, &obj)
|
|
}
|
|
|
|
// deepCopyJson - helper function to manipulate JSON Objects.
|
|
// Makes deep copy of json object by converting to JSON and back.
|
|
func deepCopyJson(in map[string]interface{}) (map[string]interface{}, error) {
|
|
bytes, err := json.Marshal(in)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
res := map[string]interface{}{}
|
|
err = json.Unmarshal(bytes, &res)
|
|
return res, err
|
|
}
|