From 1ce62e556475677e73a1c0881629ce9e8e299fc2 Mon Sep 17 00:00:00 2001 From: Nic Pottier Date: Mon, 12 Jun 2017 12:57:38 -0500 Subject: [PATCH] Add support for ToBool for json fragments, deal with escaped strings --- utils/conversions.go | 35 +++++++++++++++++++++++++-- utils/conversions_test.go | 51 +++++++++++++++++++++++++++++++++++++++ utils/json.go | 21 +++++++++++++--- utils/json_test.go | 1 + 4 files changed, 103 insertions(+), 5 deletions(-) diff --git a/utils/conversions.go b/utils/conversions.go index 22b26158a..df9cf1394 100644 --- a/utils/conversions.go +++ b/utils/conversions.go @@ -469,10 +469,41 @@ func ToBool(env Environment, test interface{}) (bool, error) { return !test.IsZero(), nil case string: - return test != "", nil + return test != "" && strings.ToLower(test) != "false", nil + + case JSONFragment: + asString, err := ToString(env, test) + if err != nil { + return false, err + } + // is this a number? + num, err := ToDecimal(env, asString) + if err == nil { + return !num.Equals(decimal.Zero), nil + } + + noWhite := strings.Join(strings.Fields(asString), "") + + // empty array? + if noWhite == "[]" { + return false, nil + } + + // empty dict + if noWhite == "{}" { + return false, nil + } + + // finally just string version + return asString != "" && strings.ToLower(asString) != "false", nil + } + + asString, err := ToString(env, test) + if err != nil { + return false, err } - return false, fmt.Errorf("ToBool unknown type '%s' with value '%+v'", reflect.TypeOf(test), test) + return ToBool(env, asString) } // XType is an an enumeration of the possible types we can deal with diff --git a/utils/conversions_test.go b/utils/conversions_test.go index 70552c894..71ac6624a 100644 --- a/utils/conversions_test.go +++ b/utils/conversions_test.go @@ -125,6 +125,57 @@ func TestToDecimal(t *testing.T) { } } +func TestToBool(t *testing.T) { + testResolver := &resolver{"155"} + + var tests = []struct { + input interface{} + expected bool + hasError bool + }{ + {nil, false, false}, + {fmt.Errorf("Error"), false, true}, + {decimal.NewFromFloat(42), true, false}, + {int(0), false, false}, + {int(15), true, false}, + {int32(15), true, false}, + {int64(15), true, false}, + {float32(15.5), true, false}, + {float64(15.5), true, false}, + {"15.5", true, false}, + {"lO.5", true, false}, + {"", false, false}, + {testResolver, true, false}, + {NewJSONFragment([]byte(`false`)), false, false}, + {NewJSONFragment([]byte(`true`)), true, false}, + {NewJSONFragment([]byte(`[]`)), false, false}, + {NewJSONFragment([]byte(`15.5`)), true, false}, + {NewJSONFragment([]byte(`0`)), false, false}, + {NewJSONFragment([]byte(`[5]`)), true, false}, + {NewJSONFragment([]byte("{\n}")), false, false}, + {NewJSONFragment([]byte(`{"one": "two"}`)), true, false}, + {struct{}{}, false, true}, + } + + env := NewDefaultEnvironment() + + for _, test := range tests { + result, err := ToBool(env, test.input) + + if err != nil && !test.hasError { + t.Errorf("Unexpected error calling ToBool on '%v': %s", test.input, err) + } + + if err == nil && test.hasError { + t.Errorf("Did not receive expected error calling ToBool on '%v': %s", test.input, err) + } + + if result != test.expected { + t.Errorf("Unexpected result calling ToBool on '%v', got: %s expected: %s", test.input, result, test.expected) + } + } +} + func TestToJSON(t *testing.T) { strMap := make(map[string]string) strMap["one"] = "1.0" diff --git a/utils/json.go b/utils/json.go index fe911ba51..3b542894f 100644 --- a/utils/json.go +++ b/utils/json.go @@ -34,15 +34,30 @@ func (j JSONFragment) Resolve(key string) interface{} { // this is a numerical index, convert to jsonparser format if err == nil { jIdx := "[" + key + "]" - val, _, _, err := jsonparser.Get(j.json, jIdx) + val, valType, _, err := jsonparser.Get(j.json, jIdx) if err == nil { - return JSONFragment{val} + if err == nil { + if valType == jsonparser.String { + strVal, err := jsonparser.ParseString(val) + if err == nil { + return strVal + } + } + return JSONFragment{val} + } } } - val, _, _, err := jsonparser.Get(j.json, key) + val, valType, _, err := jsonparser.Get(j.json, key) if err != nil { return err } + + if valType == jsonparser.String { + strVal, err := jsonparser.ParseString(val) + if err == nil { + return strVal + } + } return JSONFragment{val} } diff --git a/utils/json_test.go b/utils/json_test.go index 795d825af..315224472 100644 --- a/utils/json_test.go +++ b/utils/json_test.go @@ -13,6 +13,7 @@ func TestJSON(t *testing.T) { {nil, "key", ""}, {[]byte(`malformed`), "key", ""}, {[]byte(`["one", "two", "three"]`), "0", "one"}, + {[]byte(`["escaped \"string\""]`), "0", `escaped "string"`}, {[]byte(`{"1": "one"}`), "1", "one"}, {[]byte(`{"arr": ["one", "two"]}`), "arr[1]", "two"}, {[]byte(`{"arr": ["one", "two"]}`), "arr.1", "two"},