Decringe
This commit is contained in:
@@ -89,7 +89,7 @@ func ProcessJSON(content string, command utils.ModifyCommand, filename string) (
|
|||||||
return commands, fmt.Errorf("failed to convert Lua table back to Go: %v", err)
|
return commands, fmt.Errorf("failed to convert Lua table back to Go: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
commands, err = applySurgicalJSONChanges(content, jsonData, goData)
|
commands, err = applyJSONChanges(content, jsonData, goData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
processJsonLogger.Error("Failed to apply JSON changes: %v", err)
|
processJsonLogger.Error("Failed to apply JSON changes: %v", err)
|
||||||
return commands, fmt.Errorf("failed to apply JSON changes: %v", err)
|
return commands, fmt.Errorf("failed to apply JSON changes: %v", err)
|
||||||
@@ -100,35 +100,36 @@ func ProcessJSON(content string, command utils.ModifyCommand, filename string) (
|
|||||||
return commands, nil
|
return commands, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// applySurgicalJSONChanges compares original and modified data and applies changes surgically
|
// applyJSONChanges compares original and modified data and applies changes surgically
|
||||||
func applySurgicalJSONChanges(content string, originalData, modifiedData interface{}) ([]utils.ReplaceCommand, error) {
|
func applyJSONChanges(content string, originalData, modifiedData interface{}) ([]utils.ReplaceCommand, error) {
|
||||||
var commands []utils.ReplaceCommand
|
var commands []utils.ReplaceCommand
|
||||||
|
|
||||||
// Apply surgical changes
|
|
||||||
appliedCommands, err := applyChanges(content, originalData, modifiedData)
|
appliedCommands, err := applyChanges(content, originalData, modifiedData)
|
||||||
if err == nil && len(appliedCommands) > 0 {
|
if err == nil && len(appliedCommands) > 0 {
|
||||||
return appliedCommands, nil
|
return appliedCommands, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return commands, fmt.Errorf("failed to make any changes to the json")
|
return commands, fmt.Errorf("failed to make any changes to the json")
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyChanges attempts to make surgical changes while preserving exact formatting
|
// applyChanges attempts to make surgical changes while preserving exact formatting
|
||||||
func applyChanges(content string, originalData, modifiedData interface{}) ([]utils.ReplaceCommand, error) {
|
func applyChanges(content string, originalData, modifiedData interface{}) ([]utils.ReplaceCommand, error) {
|
||||||
var commands []utils.ReplaceCommand
|
var commands []utils.ReplaceCommand
|
||||||
|
|
||||||
// Find all changes between original and modified data
|
// Find all changes between original and modified data
|
||||||
changes := findDeepChanges("", originalData, modifiedData)
|
changes := findDeepChanges("", originalData, modifiedData)
|
||||||
|
|
||||||
|
jsonLogger.Debug("applyChanges: Found %d changes: %v", len(changes), changes)
|
||||||
|
|
||||||
if len(changes) == 0 {
|
if len(changes) == 0 {
|
||||||
return commands, nil
|
return commands, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort removal operations by index in descending order to avoid index shifting
|
// Sort removal operations by index in descending order to avoid index shifting
|
||||||
var removals []string
|
var removals []string
|
||||||
var additions []string
|
var additions []string
|
||||||
var valueChanges []string
|
var valueChanges []string
|
||||||
|
|
||||||
for path := range changes {
|
for path := range changes {
|
||||||
if strings.HasSuffix(path, "@remove") {
|
if strings.HasSuffix(path, "@remove") {
|
||||||
removals = append(removals, path)
|
removals = append(removals, path)
|
||||||
@@ -138,23 +139,21 @@ func applyChanges(content string, originalData, modifiedData interface{}) ([]uti
|
|||||||
valueChanges = append(valueChanges, path)
|
valueChanges = append(valueChanges, path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonLogger.Info("applyChanges: Found %d changes: %v", len(changes), changes)
|
jsonLogger.Debug("applyChanges: %d removals, %d additions, %d value changes", len(removals), len(additions), len(valueChanges))
|
||||||
|
|
||||||
jsonLogger.Info("applyChanges: %d removals, %d additions, %d value changes", len(removals), len(additions), len(valueChanges))
|
|
||||||
|
|
||||||
// Apply removals first (from end to beginning to avoid index shifting)
|
// Apply removals first (from end to beginning to avoid index shifting)
|
||||||
for _, removalPath := range removals {
|
for _, removalPath := range removals {
|
||||||
actualPath := strings.TrimSuffix(removalPath, "@remove")
|
actualPath := strings.TrimSuffix(removalPath, "@remove")
|
||||||
index := extractIndexFromRemovalPath(removalPath)
|
index := extractIndexFromRemovalPath(removalPath)
|
||||||
arrayPath := getArrayPathFromElementPath(actualPath)
|
arrayPath := getArrayPathFromElementPath(actualPath)
|
||||||
|
|
||||||
// Get the array element to remove
|
// Get the array element to remove
|
||||||
result := gjson.Get(content, actualPath)
|
result := gjson.Get(content, actualPath)
|
||||||
if !result.Exists() {
|
if !result.Exists() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the exact byte range to remove (including comma/formatting)
|
// Find the exact byte range to remove (including comma/formatting)
|
||||||
startPos, endPos := findArrayElementRemovalRange(content, arrayPath, index)
|
startPos, endPos := findArrayElementRemovalRange(content, arrayPath, index)
|
||||||
if startPos >= 0 && endPos > startPos {
|
if startPos >= 0 && endPos > startPos {
|
||||||
@@ -165,20 +164,20 @@ func applyChanges(content string, originalData, modifiedData interface{}) ([]uti
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply additions (new fields)
|
// Apply additions (new fields)
|
||||||
for _, additionPath := range additions {
|
for _, additionPath := range additions {
|
||||||
actualPath := strings.TrimSuffix(additionPath, "@add")
|
actualPath := strings.TrimSuffix(additionPath, "@add")
|
||||||
newValue := changes[additionPath]
|
newValue := changes[additionPath]
|
||||||
|
|
||||||
jsonLogger.Info("Processing addition: path=%s, value=%v", actualPath, newValue)
|
jsonLogger.Debug("Processing addition: path=%s, value=%v", actualPath, newValue)
|
||||||
|
|
||||||
// Find the parent object to add the field to
|
// Find the parent object to add the field to
|
||||||
parentPath := getParentPath(actualPath)
|
parentPath := getParentPath(actualPath)
|
||||||
fieldName := getFieldName(actualPath)
|
fieldName := getFieldName(actualPath)
|
||||||
|
|
||||||
jsonLogger.Info("Parent path: %s, field name: %s", parentPath, fieldName)
|
jsonLogger.Debug("Parent path: %s, field name: %s", parentPath, fieldName)
|
||||||
|
|
||||||
// Get the parent object
|
// Get the parent object
|
||||||
var parentResult gjson.Result
|
var parentResult gjson.Result
|
||||||
if parentPath == "" {
|
if parentPath == "" {
|
||||||
@@ -187,34 +186,34 @@ func applyChanges(content string, originalData, modifiedData interface{}) ([]uti
|
|||||||
} else {
|
} else {
|
||||||
parentResult = gjson.Get(content, parentPath)
|
parentResult = gjson.Get(content, parentPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !parentResult.Exists() {
|
if !parentResult.Exists() {
|
||||||
jsonLogger.Info("Parent path %s does not exist, skipping", parentPath)
|
jsonLogger.Debug("Parent path %s does not exist, skipping", parentPath)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find where to insert the new field (at the end of the object)
|
// Find where to insert the new field (at the end of the object)
|
||||||
startPos := int(parentResult.Index + len(parentResult.Raw) - 1) // Before closing brace
|
startPos := int(parentResult.Index + len(parentResult.Raw) - 1) // Before closing brace
|
||||||
|
|
||||||
jsonLogger.Info("Inserting at pos %d", startPos)
|
jsonLogger.Debug("Inserting at pos %d", startPos)
|
||||||
|
|
||||||
// Convert the new value to JSON string
|
// Convert the new value to JSON string
|
||||||
newValueStr := convertValueToJSONString(newValue)
|
newValueStr := convertValueToJSONString(newValue)
|
||||||
|
|
||||||
// Insert the new field
|
// Insert the new field
|
||||||
insertText := fmt.Sprintf(`,"%s":%s`, fieldName, newValueStr)
|
insertText := fmt.Sprintf(`,"%s":%s`, fieldName, newValueStr)
|
||||||
|
|
||||||
jsonLogger.Info("Inserting text: %q", insertText)
|
jsonLogger.Debug("Inserting text: %q", insertText)
|
||||||
|
|
||||||
commands = append(commands, utils.ReplaceCommand{
|
commands = append(commands, utils.ReplaceCommand{
|
||||||
From: startPos,
|
From: startPos,
|
||||||
To: startPos,
|
To: startPos,
|
||||||
With: insertText,
|
With: insertText,
|
||||||
})
|
})
|
||||||
|
|
||||||
jsonLogger.Info("Added addition command: From=%d, To=%d, With=%q", startPos, startPos, insertText)
|
jsonLogger.Debug("Added addition command: From=%d, To=%d, With=%q", startPos, startPos, insertText)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply value changes (in reverse order to avoid position shifting)
|
// Apply value changes (in reverse order to avoid position shifting)
|
||||||
sort.Slice(valueChanges, func(i, j int) bool {
|
sort.Slice(valueChanges, func(i, j int) bool {
|
||||||
// Get positions for comparison
|
// Get positions for comparison
|
||||||
@@ -222,40 +221,40 @@ func applyChanges(content string, originalData, modifiedData interface{}) ([]uti
|
|||||||
resultJ := gjson.Get(content, valueChanges[j])
|
resultJ := gjson.Get(content, valueChanges[j])
|
||||||
return resultI.Index > resultJ.Index // Descending order
|
return resultI.Index > resultJ.Index // Descending order
|
||||||
})
|
})
|
||||||
|
|
||||||
for _, path := range valueChanges {
|
for _, path := range valueChanges {
|
||||||
newValue := changes[path]
|
newValue := changes[path]
|
||||||
|
|
||||||
jsonLogger.Info("Processing value change: path=%s, value=%v", path, newValue)
|
jsonLogger.Debug("Processing value change: path=%s, value=%v", path, newValue)
|
||||||
|
|
||||||
// Get the current value and its position in the original JSON
|
// Get the current value and its position in the original JSON
|
||||||
result := gjson.Get(content, path)
|
result := gjson.Get(content, path)
|
||||||
if !result.Exists() {
|
if !result.Exists() {
|
||||||
jsonLogger.Info("Path %s does not exist, skipping", path)
|
jsonLogger.Debug("Path %s does not exist, skipping", path)
|
||||||
continue // Skip if path doesn't exist
|
continue // Skip if path doesn't exist
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the exact byte positions of this value
|
// Get the exact byte positions of this value
|
||||||
startPos := result.Index
|
startPos := result.Index
|
||||||
endPos := startPos + len(result.Raw)
|
endPos := startPos + len(result.Raw)
|
||||||
|
|
||||||
jsonLogger.Info("Found value at pos %d-%d: %q", startPos, endPos, result.Raw)
|
jsonLogger.Debug("Found value at pos %d-%d: %q", startPos, endPos, result.Raw)
|
||||||
|
|
||||||
// Convert the new value to JSON string
|
// Convert the new value to JSON string
|
||||||
newValueStr := convertValueToJSONString(newValue)
|
newValueStr := convertValueToJSONString(newValue)
|
||||||
|
|
||||||
jsonLogger.Info("Converting to: %q", newValueStr)
|
jsonLogger.Debug("Converting to: %q", newValueStr)
|
||||||
|
|
||||||
// Create a replacement command for this specific value
|
// Create a replacement command for this specific value
|
||||||
commands = append(commands, utils.ReplaceCommand{
|
commands = append(commands, utils.ReplaceCommand{
|
||||||
From: int(startPos),
|
From: int(startPos),
|
||||||
To: int(endPos),
|
To: int(endPos),
|
||||||
With: newValueStr,
|
With: newValueStr,
|
||||||
})
|
})
|
||||||
|
|
||||||
jsonLogger.Info("Added command: From=%d, To=%d, With=%q", int(startPos), int(endPos), newValueStr)
|
jsonLogger.Debug("Added command: From=%d, To=%d, With=%q", int(startPos), int(endPos), newValueStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return commands, nil
|
return commands, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,7 +376,7 @@ func findDeepChanges(basePath string, original, modified interface{}) map[string
|
|||||||
} else {
|
} else {
|
||||||
currentPath = basePath + "." + key
|
currentPath = basePath + "." + key
|
||||||
}
|
}
|
||||||
|
|
||||||
if origValue, exists := orig[key]; exists {
|
if origValue, exists := orig[key]; exists {
|
||||||
// Key exists in both, check if value changed
|
// Key exists in both, check if value changed
|
||||||
switch modValue.(type) {
|
switch modValue.(type) {
|
||||||
|
Reference in New Issue
Block a user