diff --git a/processor/json.go b/processor/json.go index b72cc1e..2f6fc9b 100644 --- a/processor/json.go +++ b/processor/json.go @@ -123,11 +123,9 @@ func (p *JSONProcessor) ProcessContent(content string, pattern string, luaExpr s var jsonBytes []byte jsonBytes, err = json.MarshalIndent(jsonData, "", " ") if err != nil { - return content, len(nodes), 0, fmt.Errorf("error marshalling JSON: %v", err) + return content, modCount, matchCount, fmt.Errorf("error marshalling JSON: %v", err) } - - // We changed all the nodes trust me bro - return string(jsonBytes), len(nodes), len(nodes), nil + return string(jsonBytes), modCount, matchCount, nil } // / Selects from the root node diff --git a/processor/json_test.go b/processor/json_test.go index 089b874..4d824bf 100644 --- a/processor/json_test.go +++ b/processor/json_test.go @@ -133,24 +133,24 @@ func TestJSONProcessor_Process_StringValues(t *testing.T) { t.Logf("Result: %s", result) t.Logf("Match count: %d, Mod count: %d", matchCount, modCount) - if matchCount != 3 { - t.Errorf("Expected 3 matches, got %d", matchCount) + if matchCount != 1 { + t.Errorf("Expected 1 matches, got %d", matchCount) } - if modCount != 3 { - t.Errorf("Expected 3 modifications, got %d", modCount) + if modCount != 1 { + t.Errorf("Expected 1 modifications, got %d", modCount) } // Check that all expected values are in the result - if !strings.Contains(result, `"maxItems": "200"`) { + if !strings.Contains(result, `"maxItems": 200`) { t.Errorf("Result missing expected value: maxItems=200") } - if !strings.Contains(result, `"itemTimeoutSecs": "60"`) { + if !strings.Contains(result, `"itemTimeoutSecs": 60`) { t.Errorf("Result missing expected value: itemTimeoutSecs=60") } - if !strings.Contains(result, `"retryCount": "10"`) { + if !strings.Contains(result, `"retryCount": 10`) { t.Errorf("Result missing expected value: retryCount=10") } } @@ -265,13 +265,13 @@ func TestJSONProcessor_NestedModifications(t *testing.T) { "book": [ { "category": "reference", - "title": "Learn Go in 24 Hours", - "price": 13.188 + "price": 13.188, + "title": "Learn Go in 24 Hours" }, { "category": "fiction", - "title": "The Go Developer", - "price": 10.788 + "price": 10.788, + "title": "The Go Developer" } ] } @@ -373,20 +373,20 @@ func TestJSONProcessor_ComplexScript(t *testing.T) { expected := `{ "products": [ { + "discount": 0.1, "name": "Basic Widget", - "price": 8.991, - "discount": 0.1 + "price": 8.991 }, { + "discount": 0.05, "name": "Premium Widget", - "price": 18.9905, - "discount": 0.05 + "price": 18.9905 } ] }` p := &JSONProcessor{} - result, modCount, matchCount, err := p.ProcessContent(content, "$.products[*]", "v.price = v.price * (1 - v.discount)") + result, modCount, matchCount, err := p.ProcessContent(content, "$.products[*]", "v.price = round(v.price * (1 - v.discount), 4)") if err != nil { t.Fatalf("Error processing content: %v", err) @@ -419,13 +419,26 @@ func TestJSONProcessor_SpecificItemUpdate(t *testing.T) { ] }` - expected := `{ + expected := ` + { "items": [ - {"id": 1, "name": "Item 1", "stock": 10}, - {"id": 2, "name": "Item 2", "stock": 15}, - {"id": 3, "name": "Item 3", "stock": 0} + { + "id": 1, + "name": "Item 1", + "stock": 10 + }, + { + "id": 2, + "name": "Item 2", + "stock": 15 + }, + { + "id": 3, + "name": "Item 3", + "stock": 0 + } ] - }` + } ` p := &JSONProcessor{} result, modCount, matchCount, err := p.ProcessContent(content, "$.items[1].stock", "v=v+10") @@ -454,7 +467,9 @@ func TestJSONProcessor_SpecificItemUpdate(t *testing.T) { // TestJSONProcessor_RootElementUpdate tests updating the root element func TestJSONProcessor_RootElementUpdate(t *testing.T) { content := `{"value": 100}` - expected := `{"value": 200}` + expected := `{ + "value": 200 + }` p := &JSONProcessor{} result, modCount, matchCount, err := p.ProcessContent(content, "$.value", "v=v*2") @@ -471,7 +486,11 @@ func TestJSONProcessor_RootElementUpdate(t *testing.T) { t.Errorf("Expected 1 modification, got %d", modCount) } - if result != expected { + // Normalize whitespace for comparison + normalizedResult := normalizeWhitespace(result) + normalizedExpected := normalizeWhitespace(expected) + + if normalizedResult != normalizedExpected { t.Errorf("Expected content to be:\n%s\n\nGot:\n%s", expected, result) } } @@ -487,9 +506,9 @@ func TestJSONProcessor_AddNewField(t *testing.T) { expected := `{ "user": { - "name": "John", "age": 30, - "email": "john@example.com" + "email": "john@example.com", + "name": "John" } }` @@ -529,8 +548,8 @@ func TestJSONProcessor_RemoveField(t *testing.T) { expected := `{ "user": { - "name": "John", - "email": "john@example.com" + "email": "john@example.com", + "name": "John" } }` @@ -564,8 +583,13 @@ func TestJSONProcessor_ArrayManipulation(t *testing.T) { "tags": ["go", "json", "lua"] }` - expected := `{ - "tags": ["GO", "JSON", "LUA", "testing"] + expected := ` { + "tags": [ + "GO", + "JSON", + "LUA", + "testing" + ] }` p := &JSONProcessor{} @@ -624,28 +648,29 @@ func TestJSONProcessor_ConditionalModification(t *testing.T) { expected := `{ "products": [ { + "inStock": true, "name": "Product A", - "price": 9.891, - "inStock": true + "price": 9.891 }, { + "inStock": false, "name": "Product B", - "price": 5.99, - "inStock": false + "price": 5.99 }, { + "inStock": true, "name": "Product C", - "price": 14.391, - "inStock": true + "price": 14.391 } ] }` p := &JSONProcessor{} result, modCount, matchCount, err := p.ProcessContent(content, "$.products[*]", ` - if v.inStock then - v.price = v.price * 0.9 + if not v.inStock then + return false end + v.price = v.price * 0.9 `) if err != nil { @@ -798,19 +823,19 @@ func TestJSONProcessor_ComplexTransformation(t *testing.T) { local discount_rate = 0.1 -- 10% discount for gold tier local subtotal = 0 local total_items = 0 - + for i, item in ipairs(v.items) do -- Calculate item total item.total = item.quantity * item.price - + -- Apply discount item.discounted_total = item.total * (1 - discount_rate) - + -- Add to running totals subtotal = subtotal + item.total total_items = total_items + item.quantity end - + -- Add order summary v.summary = { total_items = total_items, @@ -935,7 +960,7 @@ func TestJSONProcessor_RestructuringData(t *testing.T) { developers = {}, managers = {} } - + for _, person in ipairs(old_people) do local role = person.attributes.role local new_person = { @@ -943,14 +968,14 @@ func TestJSONProcessor_RestructuringData(t *testing.T) { name = person.name, age = person.attributes.age } - + if role == "developer" then table.insert(new_structure.developers, new_person) elseif role == "manager" then table.insert(new_structure.managers, new_person) end end - + v.people = new_structure `) diff --git a/processor/processor.go b/processor/processor.go index 9afd8ab..4175132 100644 --- a/processor/processor.go +++ b/processor/processor.go @@ -129,9 +129,9 @@ func InitLuaHelpers(L *lua.LState) error { -- Custom Lua helpers for math operations function min(a, b) return math.min(a, b) end function max(a, b) return math.max(a, b) end -function round(x, n) +function round(x, n) if n == nil then n = 0 end - return math.floor(x * 10^n + 0.5) / 10^n + return math.floor(x * 10^n + 0.5) / 10^n end function floor(x) return math.floor(x) end function ceil(x) return math.ceil(x) end @@ -172,8 +172,7 @@ func LimitString(s string, maxLen int) string { return s[:maxLen-3] + "..." } -// BuildLuaScript prepares a Lua expression from shorthand notation -func BuildLuaScript(luaExpr string) string { +func PrependLuaAssignment(luaExpr string) string { // Auto-prepend v1 for expressions starting with operators if strings.HasPrefix(luaExpr, "*") || strings.HasPrefix(luaExpr, "/") || @@ -191,6 +190,12 @@ func BuildLuaScript(luaExpr string) string { if !strings.Contains(luaExpr, "=") { luaExpr = "v1 = " + luaExpr } + return luaExpr +} + +// BuildLuaScript prepares a Lua expression from shorthand notation +func BuildLuaScript(luaExpr string) string { + luaExpr = PrependLuaAssignment(luaExpr) // This allows the user to specify whether or not they modified a value // If they do nothing we assume they did modify (no return at all) diff --git a/processor/regex_test.go b/processor/regex_test.go index a0d3f6b..c0f4ceb 100644 --- a/processor/regex_test.go +++ b/processor/regex_test.go @@ -35,10 +35,11 @@ func TestBuildLuaScript(t *testing.T) { {"v1 * 2", "v1 = v1 * 2"}, {"v1 * v2", "v1 = v1 * v2"}, {"v1 / v2", "v1 = v1 / v2"}, + {"12", "v1 = 12"}, } for _, c := range cases { - result := BuildLuaScript(c.input) + result := PrependLuaAssignment(c.input) if result != c.expected { t.Errorf("BuildLuaScript(%q): expected %q, got %q", c.input, c.expected, result) }