Hallucinate actual json fucking thing

This commit is contained in:
2025-08-21 22:18:34 +02:00
parent 1a8c0b9f90
commit fd1df6e40e
2 changed files with 87 additions and 45 deletions

View File

@@ -7,7 +7,6 @@ import (
"time" "time"
logger "git.site.quack-lab.dev/dave/cylogger" logger "git.site.quack-lab.dev/dave/cylogger"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson" "github.com/tidwall/sjson"
lua "github.com/yuin/gopher-lua" lua "github.com/yuin/gopher-lua"
) )
@@ -119,8 +118,8 @@ func applySurgicalJSONChanges(content string, originalData, modifiedData interfa
return commands, nil return commands, nil
} }
// Try surgical approach first // Try true surgical approach that preserves formatting
surgicalCommands, err := applySurgicalChanges(content, originalData, modifiedData) surgicalCommands, err := applyTrueSurgicalChanges(content, originalData, modifiedData)
if err == nil && len(surgicalCommands) > 0 { if err == nil && len(surgicalCommands) > 0 {
return surgicalCommands, nil return surgicalCommands, nil
} }
@@ -140,21 +139,18 @@ func applySurgicalJSONChanges(content string, originalData, modifiedData interfa
return commands, nil return commands, nil
} }
// applySurgicalChanges attempts to make surgical changes using gjson and sjson // applyTrueSurgicalChanges attempts to make surgical changes while preserving exact formatting
func applySurgicalChanges(content string, originalData, modifiedData interface{}) ([]utils.ReplaceCommand, error) { func applyTrueSurgicalChanges(content string, originalData, modifiedData interface{}) ([]utils.ReplaceCommand, error) {
var commands []utils.ReplaceCommand var commands []utils.ReplaceCommand
// Parse the original content with gjson to get the structure
result := gjson.Parse(content)
// Find changes by comparing the data structures // Find changes by comparing the data structures
changes := findSurgicalChanges(result, originalData, modifiedData) changes := findDeepChanges("", originalData, modifiedData)
if len(changes) == 0 { if len(changes) == 0 {
return commands, nil return commands, nil
} }
// Apply changes surgically // Apply changes surgically using sjson.Set() to preserve formatting
modifiedContent := content modifiedContent := content
for path, newValue := range changes { for path, newValue := range changes {
var err error var err error
@@ -165,59 +161,94 @@ func applySurgicalChanges(content string, originalData, modifiedData interface{}
} }
// If we successfully made changes, create a replacement command // If we successfully made changes, create a replacement command
// But ensure we preserve formatting by using json.MarshalIndent
if modifiedContent != content { if modifiedContent != content {
// Parse the surgically modified content and re-format it
var parsedData interface{}
if err := json.Unmarshal([]byte(modifiedContent), &parsedData); err != nil {
return nil, fmt.Errorf("failed to parse surgically modified content: %v", err)
}
formattedContent, err := json.MarshalIndent(parsedData, "", " ")
if err != nil {
return nil, fmt.Errorf("failed to format surgically modified content: %v", err)
}
commands = append(commands, utils.ReplaceCommand{ commands = append(commands, utils.ReplaceCommand{
From: 0, From: 0,
To: len(content), To: len(content),
With: string(formattedContent), With: modifiedContent,
}) })
} }
return commands, nil return commands, nil
} }
// findSurgicalChanges finds specific paths that need to be changed // findDeepChanges recursively finds all paths that need to be changed
func findSurgicalChanges(result gjson.Result, original, modified interface{}) map[string]interface{} { func findDeepChanges(basePath string, original, modified interface{}) map[string]interface{} {
changes := make(map[string]interface{}) changes := make(map[string]interface{})
switch orig := original.(type) { switch orig := original.(type) {
case map[string]interface{}: case map[string]interface{}:
if mod, ok := modified.(map[string]interface{}); ok { if mod, ok := modified.(map[string]interface{}); ok {
// Check each key in the modified data
for key, modValue := range mod { for key, modValue := range mod {
var currentPath string
if basePath == "" {
currentPath = key
} else {
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
if !deepEqual(origValue, modValue) { if !deepEqual(origValue, modValue) {
changes[key] = modValue // If it's a nested object/array, recurse
switch modValue.(type) {
case map[string]interface{}, []interface{}:
nestedChanges := findDeepChanges(currentPath, origValue, modValue)
for nestedPath, nestedValue := range nestedChanges {
changes[nestedPath] = nestedValue
}
default:
// Primitive value changed
changes[currentPath] = modValue
}
} }
} else { } else {
// New key added // New key added
changes[key] = modValue changes[currentPath] = modValue
} }
} }
} }
case []interface{}: case []interface{}:
if mod, ok := modified.([]interface{}); ok { if mod, ok := modified.([]interface{}); ok {
// For arrays, we'll do a simple replacement for now // For arrays, check each index
if !deepEqual(orig, mod) { for i, modValue := range mod {
changes[""] = mod // Root path for array replacement var currentPath string
if basePath == "" {
currentPath = fmt.Sprintf("%d", i)
} else {
currentPath = fmt.Sprintf("%s.%d", basePath, i)
}
if i < len(orig) {
// Index exists in both, check if value changed
if !deepEqual(orig[i], modValue) {
// If it's a nested object/array, recurse
switch modValue.(type) {
case map[string]interface{}, []interface{}:
nestedChanges := findDeepChanges(currentPath, orig[i], modValue)
for nestedPath, nestedValue := range nestedChanges {
changes[nestedPath] = nestedValue
}
default:
// Primitive value changed
changes[currentPath] = modValue
}
}
} else {
// New array element added
changes[currentPath] = modValue
}
} }
} }
default: default:
// For primitive types, compare directly // For primitive types, compare directly
if !deepEqual(original, modified) { if !deepEqual(original, modified) {
if basePath == "" {
changes[""] = modified changes[""] = modified
} else {
changes[basePath] = modified
}
} }
} }

11
test_surgical.yml Normal file
View File

@@ -0,0 +1,11 @@
- name: SurgicalWeightTest
json: true
lua: |
-- This demonstrates surgical JSON editing
-- Only the Weight field of Item_Fiber will be modified
data.Rows[1].Weight = 999
modified = true
files:
- 'D_Itemable.json'
reset: false
loglevel: INFO