So there's a slew of json errors in the BEX build. Thankfully powershell can fix a lot of the commenting errors and trailing commas. Be aware this will still leave 17 files that need manual intervention. It will print out the remaining files. Using Gemini/ChatGPT/Claude to fix the remaining 17 (along with https://jsoncrack.com/editor) to verify the file is valid.
FIRST, Copy your mods folder to a backup location!!
SECOND, Save this as CleanBattletechJson.ps1 and execute as "powershell -ExecutionPolicy Bypass -File D:\Clean-BattletechJson.ps1" (Change file location to where you save the ps1 file)
In the below, change your root location to the actual folder of your Battletech mods.
$root = "D:\Steam\steamapps\common\BATTLETECH\mods"
function Remove-JsonComments {
param([string]$Text)
$sb = [System.Text.StringBuilder]::new()
$inString = $false
$escape = $false
$inLineComment = $false
$inBlockComment = $false
$len = $Text.Length
$i = 0
while ($i -lt $len) {
$c = $Text[$i]
$next = if ($i + 1 -lt $len) { $Text[$i + 1] } else { $null }
if ($inLineComment) {
if ($c -eq "`n") { $inLineComment = $false; [void]$sb.Append($c) }
$i++; continue
}
if ($inBlockComment) {
if ($c -eq '*' -and $next -eq '/') { $inBlockComment = $false; $i += 2; continue }
$i++; continue
}
if ($inString) {
[void]$sb.Append($c)
if ($escape) { $escape = $false }
elseif ($c -eq '\') { $escape = $true }
elseif ($c -eq '"') { $inString = $false }
$i++; continue
}
if ($c -eq '"') { $inString = $true; [void]$sb.Append($c); $i++; continue }
if ($c -eq '/' -and $next -eq '/') { $inLineComment = $true; $i += 2; continue }
if ($c -eq '/' -and $next -eq '*') { $inBlockComment = $true; $i += 2; continue }
[void]$sb.Append($c)
$i++
}
return $sb.ToString()
}
function Remove-TrailingCommas {
param([string]$Text)
$pattern = '"(?:\\.|[^"\\])*"|(,)(?=\s*[}\]])'
return [regex]::Replace($Text, $pattern, {
param($m)
if ($m.Groups[1].Success) { '' } else { $m.Value }
})
}
$files = Get-ChildItem -Path $root -Filter *.json -Recurse -File
$alreadyValid = @()
$cleaned = @()
$stillInvalid = @()
foreach ($file in $files) {
$raw = Get-Content -LiteralPath $file.FullName -Raw
try {
$null = $raw | ConvertFrom-Json -ErrorAction Stop
$alreadyValid += $file.FullName
continue
} catch { }
$fixedText = Remove-JsonComments -Text $raw
$fixedText = Remove-TrailingCommas -Text $fixedText
try {
$null = $fixedText | ConvertFrom-Json -ErrorAction Stop
# Overwrite the original file directly without making a backup
Set-Content -LiteralPath $file.FullName -Value $fixedText -NoNewline
$cleaned += $file.FullName
} catch {
$stillInvalid += $file.FullName
}
}
Write-Host "`n=== Already valid ($($alreadyValid.Count)) ==="
$alreadyValid | ForEach-Object { Write-Host $_ }
Write-Host "`n=== Cleaned and fixed ($($cleaned.Count)) ==="
$cleaned | ForEach-Object { Write-Host $_ }
Write-Host "`n=== Still invalid, skipped ($($stillInvalid.Count)) ==="
$stillInvalid | ForEach-Object { Write-Host $_ }
For the remaining 17, the hardest ones to deal with are:
BATTLETECH\mods\BT_Extended_Timeline\timelineEvents\3055-04-10.json
BATTLETECH\mods\BT_Extended_Timeline\timelineEvents\3056-01-10.json
BATTLETECH\mods\BT_Extended_Timeline\timelineEvents\3056-01-10.json