Add support for getting the length of the string or the slice of a json path

This commit is contained in:
TwinProduction
2020-08-12 21:42:13 -04:00
parent 937b136e60
commit da92907873
7 changed files with 68 additions and 35 deletions

View File

@ -8,26 +8,30 @@ import (
)
// Eval is a half-baked json path implementation that needs some love
func Eval(path string, b []byte) (string, error) {
func Eval(path string, b []byte) (string, int, error) {
var object interface{}
err := json.Unmarshal(b, &object)
if err != nil {
// Try to unmarshal it into an array instead
return "", err
return "", 0, err
}
return walk(path, object)
}
func walk(path string, object interface{}) (string, error) {
func walk(path string, object interface{}) (string, int, error) {
keys := strings.Split(path, ".")
currentKey := keys[0]
switch value := extractValue(currentKey, object).(type) {
case map[string]interface{}:
return walk(strings.Replace(path, fmt.Sprintf("%s.", currentKey), "", 1), value)
case string:
return value, len(value), nil
case []interface{}:
return fmt.Sprintf("%v", value), len(value), nil
case interface{}:
return fmt.Sprintf("%v", value), nil
return fmt.Sprintf("%v", value), 1, nil
default:
return "", fmt.Errorf("couldn't walk through '%s' because type was '%T', but expected 'map[string]interface{}'", currentKey, value)
return "", 0, fmt.Errorf("couldn't walk through '%s' because type was '%T', but expected 'map[string]interface{}'", currentKey, value)
}
}

View File

@ -8,10 +8,13 @@ func TestEval(t *testing.T) {
expectedOutput := "value"
output, err := Eval(path, []byte(data))
output, outputLength, err := Eval(path, []byte(data))
if err != nil {
t.Error("Didn't expect any error, but got", err)
}
if outputLength != len(expectedOutput) {
t.Errorf("Expected output length to be %v, but was %v", len(expectedOutput), outputLength)
}
if output != expectedOutput {
t.Errorf("Expected output to be %v, but was %v", expectedOutput, output)
}
@ -23,7 +26,7 @@ func TestEvalWithLongSimpleWalk(t *testing.T) {
expectedOutput := "value"
output, err := Eval(path, []byte(data))
output, _, err := Eval(path, []byte(data))
if err != nil {
t.Error("Didn't expect any error, but got", err)
}
@ -38,10 +41,11 @@ func TestEvalWithArrayOfMaps(t *testing.T) {
expectedOutput := "2"
output, err := Eval(path, []byte(data))
output, _, err := Eval(path, []byte(data))
if err != nil {
t.Error("Didn't expect any error, but got", err)
}
if output != expectedOutput {
t.Errorf("Expected output to be %v, but was %v", expectedOutput, output)
}
@ -53,7 +57,7 @@ func TestEvalWithArrayOfValues(t *testing.T) {
expectedOutput := "1"
output, err := Eval(path, []byte(data))
output, _, err := Eval(path, []byte(data))
if err != nil {
t.Error("Didn't expect any error, but got", err)
}
@ -68,7 +72,7 @@ func TestEvalWithRootArrayOfValues(t *testing.T) {
expectedOutput := "2"
output, err := Eval(path, []byte(data))
output, _, err := Eval(path, []byte(data))
if err != nil {
t.Error("Didn't expect any error, but got", err)
}
@ -83,7 +87,7 @@ func TestEvalWithRootArrayOfMaps(t *testing.T) {
expectedOutput := "1"
output, err := Eval(path, []byte(data))
output, _, err := Eval(path, []byte(data))
if err != nil {
t.Error("Didn't expect any error, but got", err)
}
@ -96,7 +100,7 @@ func TestEvalWithRootArrayOfMapsUsingInvalidArrayIndex(t *testing.T) {
path := "[5].id"
data := `[{"id": 1}, {"id": 2}]`
_, err := Eval(path, []byte(data))
_, _, err := Eval(path, []byte(data))
if err == nil {
t.Error("Should've returned an error, but didn't")
}
@ -108,7 +112,7 @@ func TestEvalWithLongWalkAndArray(t *testing.T) {
expectedOutput := "1"
output, err := Eval(path, []byte(data))
output, _, err := Eval(path, []byte(data))
if err != nil {
t.Error("Didn't expect any error, but got", err)
}
@ -123,7 +127,7 @@ func TestEvalWithNestedArray(t *testing.T) {
expectedOutput := "7"
output, err := Eval(path, []byte(data))
output, _, err := Eval(path, []byte(data))
if err != nil {
t.Error("Didn't expect any error, but got", err)
}
@ -138,7 +142,7 @@ func TestEvalWithMapOfNestedArray(t *testing.T) {
expectedOutput := "e"
output, err := Eval(path, []byte(data))
output, _, err := Eval(path, []byte(data))
if err != nil {
t.Error("Didn't expect any error, but got", err)
}