Skip to content

Commit

Permalink
Use regex for a more reliable means of parsing path
Browse files Browse the repository at this point in the history
  • Loading branch information
colmsnowplow committed Aug 10, 2022
1 parent 4dbbd67 commit 41e0325
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 25 deletions.
35 changes: 21 additions & 14 deletions pkg/transform/snowplow_enriched_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,26 +204,33 @@ func NewSpEnrichedFilterFunctionUnstructEvent(eventNameToMatch, eventVersionToMa
return createSpEnrichedFilterFunction(regex, regexTimeout, getUnstructValuesForMatch)
}

// parsePathToArguments parses a string path to custom data (eg. `test1.test2[0].test3`)
// into the slice of interfaces expected by the analytics SDK's Get() methods.
func parsePathToArguments(pathToField string) ([]interface{}, error) {
splitPath := strings.Split(pathToField, ".")
// validate that an edge case (unmatched opening brace) isn't present
if strings.Count(pathToField, "[") != strings.Count(pathToField, "]") {
return nil, errors.New(fmt.Sprint("unmatched brace in path: ", pathToField))
}

convertedPath := make([]interface{}, 0)
for _, element := range splitPath {
splitElement := strings.Split(element, "[")
// regex to separate path into components
re := regexp.MustCompile(`\[\d+\]|[^\.\[]+`)
parts := re.FindAllString(pathToField, -1)

switch len(splitElement) {
case 1:
convertedPath = append(convertedPath, element)
case 2:
intString := splitElement[1][:len(splitElement[1])-1] // trim the closing brace
// regex to identify arrays
arrayRegex := regexp.MustCompile(`\[\d+\]`)

intElement, err := strconv.Atoi(intString)
convertedPath := make([]interface{}, 0)
for _, part := range parts {

if arrayRegex.MatchString(part) { // handle arrays first
intPart, err := strconv.Atoi(part[1 : len(part)-1]) // strip braces and convert to int
if err != nil {
return nil, errors.New(fmt.Sprint("error parsing path element: ", element))
return nil, errors.New(fmt.Sprint("error parsing path element: ", part))
}
convertedPath = append(convertedPath, splitElement[0], intElement)
default:
return nil, errors.New(fmt.Sprint("error parsing path element: ", element))

convertedPath = append(convertedPath, intPart)
} else { // handle strings
convertedPath = append(convertedPath, part)
}

}
Expand Down
21 changes: 10 additions & 11 deletions pkg/transform/snowplow_enriched_filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,8 +486,8 @@ func TestParsePathToArguments(t *testing.T) {
assert := assert.New(t)

// Common case
path1, err1 := parsePathToArguments("test1.test2[1].test3")
expectedPath1 := []interface{}{"test1", "test2", 1, "test3"}
path1, err1 := parsePathToArguments("test1[123].test2[1].test3")
expectedPath1 := []interface{}{"test1", 123, "test2", 1, "test3"}

assert.Equal(expectedPath1, path1)
assert.Nil(err1)
Expand All @@ -506,21 +506,20 @@ func TestParsePathToArguments(t *testing.T) {
assert.Equal(expectedPath3, path3)
assert.Nil(err3)

// Failure edge case - valid JSONpath but not accepted here
// Success edge case - nested arrays
path4, err4 := parsePathToArguments("test1.test2[1][2].test3")
expectedPath4 := []interface{}{"test1", "test2", 1, 2, "test3"}

assert.Nil(path4)
assert.NotNil(err4)
if err4 != nil {
assert.Equal("error parsing path element: test2[1][2]", err4.Error())
}
assert.Equal(expectedPath4, path4)
assert.Nil(err4)

// Failure edge case - square bracket in field name (this is surely invalid anyway, but just for completeness...)
// Failure edge case - unmatched brace in path
// We are validating for this and failing at startup, with the assumption that it must be misconfiguration.
path5, err5 := parsePathToArguments("test1.test[2.test3")

assert.Nil(path5)
assert.NotNil(err5)
if err4 != nil {
assert.Equal("error parsing path element: test[2", err5.Error())
if err5 != nil {
assert.Equal("unmatched brace in path: test1.test[2.test3", err5.Error())
}
}

0 comments on commit 41e0325

Please sign in to comment.