Skip to content

Commit

Permalink
if key not found in config, return nil value of the
Browse files Browse the repository at this point in the history
requested type instead of panic
  • Loading branch information
feliixx committed Apr 14, 2022
1 parent 6248807 commit 74d2342
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 51 deletions.
130 changes: 85 additions & 45 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"io"
"log"
"reflect"
"strconv"
"strings"
Expand Down Expand Up @@ -46,91 +47,143 @@ func SetDefault(key string, value any) {

// GetString returns the value associated with the key as a string.
func GetString(key string) string {
return cast[string](getValue(key))

val, ok := getValue(key)
if !ok {
return ""
}
return cast[string](val)
}

// GetBool returns the value associated with the key as a bool.
func GetBool(key string) bool {
return cast[bool](getValue(key))

val, ok := getValue(key)
if !ok {
return false
}
return cast[bool](val)
}

// GetInt returns the value associated with the key as an int.
func GetInt(key string) int {

n := cast[json.Number](getValue(key))
v, err := strconv.ParseInt(string(n), 10, 64)
val, ok := getValue(key)
if !ok {
return 0
}

n := cast[json.Number](val)
i, err := strconv.ParseInt(string(n), 10, 64)
if err != nil {
panic("Can't parse number '%s' as an int")
}
return int(v)
return int(i)
}

// GetInt32 returns the value associated with the key as an int32
func GetInt32(key string) int32 {
n := cast[json.Number](getValue(key))
v, err := strconv.ParseInt(string(n), 10, 32)

val, ok := getValue(key)
if !ok {
return 0
}

n := cast[json.Number](val)
i, err := strconv.ParseInt(string(n), 10, 32)
if err != nil {
panic("Can't parse number '%s' as an int32")
}
return int32(v)
return int32(i)
}

// GetInt64 returns the value associated with the key as an int64.
func GetInt64(key string) int64 {
n := cast[json.Number](getValue(key))
v, err := strconv.ParseInt(string(n), 10, 64)

val, ok := getValue(key)
if !ok {
return 0
}

n := cast[json.Number](val)
i, err := strconv.ParseInt(string(n), 10, 64)
if err != nil {
panic("Can't parse number '%s' as an int64")
}
return v
return i
}

// GetUint returns the value associated with the key as an uint.
func GetUint(key string) uint {
n := cast[json.Number](getValue(key))
v, err := strconv.ParseUint(string(n), 10, 64)

val, ok := getValue(key)
if !ok {
return 0
}

n := cast[json.Number](val)
i, err := strconv.ParseUint(string(n), 10, 64)
if err != nil {
panic("Can't parse number '%s' as an uint")
}
return uint(v)
return uint(i)
}

// GetUint32 returns the value associated with the key as an uint32.
func GetUint32(key string) uint32 {
n := cast[json.Number](getValue(key))
v, err := strconv.ParseUint(string(n), 10, 32)

val, ok := getValue(key)
if !ok {
return 0
}

n := cast[json.Number](val)
i, err := strconv.ParseUint(string(n), 10, 32)
if err != nil {
panic("Can't parse number '%s' as an uint32")
}
return uint32(v)
return uint32(i)
}

// GetUint64 returns the value associated with the key as an uint64.
func GetUint64(key string) uint64 {
n := cast[json.Number](getValue(key))
v, err := strconv.ParseUint(string(n), 10, 64)

val, ok := getValue(key)
if !ok {
return 0
}

n := cast[json.Number](val)
i, err := strconv.ParseUint(string(n), 10, 64)
if err != nil {
panic("Can't parse number '%s' as an uint64")
}
return uint64(v)
return uint64(i)
}

// GetFloat64 returns the value associated with the key as a float64.
func GetFloat64(key string) float64 {
n := cast[json.Number](getValue(key))
v, err := strconv.ParseFloat(string(n), 64)

val, ok := getValue(key)
if !ok {
return 0.0
}

n := cast[json.Number](val)
f, err := strconv.ParseFloat(string(n), 64)
if err != nil {
panic("Can't parse number '%s' as a float64")
}
return v
return f
}

// GetAny returns any value associated with the key.
func GetAny(key string) any {
return getValue(key)
v, _ := getValue(key)
return v
}

func getValue(key string) any {
func getValue(key string) (val any, ok bool) {

nProp := strings.Split(key, ".")
nested := config
Expand All @@ -140,39 +193,26 @@ func getValue(key string) any {
if i == len(nProp)-1 {

if v, ok := nested[prop]; ok {
return v
return v, ok
}

path := "'" + strings.Join(nProp[:i], ".") + "'"
if path == "''" {
path = "root object"
}

return getDefaultValueOrPanic(
key,
fmt.Sprintf("%s has no key '%s'", path, prop),
)
return getDefault(key)
}

if _, ok := nested[prop].(map[string]any); !ok {
return getDefaultValueOrPanic(
key,
fmt.Sprintf("%s is not an object", strings.Join(nProp[:i+1], ".")),
)
return getDefault(key)
}

nested = nested[prop].(map[string]any)
}

return nil
return nil, false
}

func getDefaultValueOrPanic(key, panicMsg string) any {
func getDefault(key string) (val any, ok bool) {
v, ok := defaults[key]
if !ok {
panic(panicMsg)
log.Printf("no value found for key '%s', using nil value instead", key)
}
return v
return v, ok
}

func cast[T any](v any) T {
Expand Down
50 changes: 44 additions & 6 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ func TestGetString(t *testing.T) {
name: "non existing key",
config: `{ "key": "value" }`,
property: "yellow",
panic: true,
panicMsg: `root object has no key 'yellow'`,
expected: "",
},
{
name: "one nested level",
Expand All @@ -40,15 +39,13 @@ func TestGetString(t *testing.T) {
name: "non existing nested",
config: `{"root": {"first": {"key":"value"}}}`,
property: "root.wrong.key",
panic: true,
panicMsg: `root.wrong is not an object`,
expected: "",
},
{
name: "non existing nested key",
config: `{"root": {"first": {"key":"value"}}}`,
property: "root.first.yellow",
panic: true,
panicMsg: `'root.first' has no key 'yellow'`,
expected: "",
},
{
name: "wrong type",
Expand Down Expand Up @@ -161,6 +158,47 @@ func TestAll(t *testing.T) {
want: 1.23842323,
got: boa.GetFloat64("root.float64"),
},

{
name: "bool nil value",
want: false,
got: boa.GetBool("nilvalue.bool"),
},
{
name: "int nil value",
want: int(0),
got: boa.GetInt("nilvalue.int"),
},
{
name: "int32 nil value",
want: int32(0),
got: boa.GetInt32("nilvalue.int32"),
},
{
name: "int64 nil value",
want: int64(0),
got: boa.GetInt64("nilvalue.int64"),
},
{
name: "uint nil value",
want: uint(0),
got: boa.GetUint("nilvalue.uint"),
},
{
name: "uint32 nil value",
want: uint32(0),
got: boa.GetUint32("nilvalue.uint32"),
},
{
name: "uint64 nil value",
want: uint64(0),
got: boa.GetUint64("nilvalue.uint64"),
},
{
name: "float64 nil value",
want: 0.0,
got: boa.GetFloat64("nilvalue.float64"),
},
}

for _, test := range tests {
Expand Down

0 comments on commit 74d2342

Please sign in to comment.