Я уже описал подход автоматизации действий в Notepad++ с помощью сценария WSH VB по ссылке: Поиск и замена математических операций с результатом в Notepad++. Такой подход позволяет назначить сочетание клавиш для автоматизированного действия и добавить необходимые команды в сценарий для обработки редактируемого файла.
Существует код, который добавляет свойство к каждому объекту в массиве, представленном в файле JSON:
Option Explicit
Const FileEncoding = 0 ' 0 = ASCII, -1 = Unicode, -2 = System Default
Dim objTokens, strTokenType, bTokenMatched
Dim strJSONString, varJSON, strState, i
' check if a file path was passed to the script in the only argument
If WScript.Arguments.Count <> 1 then
CreateObject("WScript.Shell").PopUp "Drop file onto the script", 3, , 48
WScript.Quit
End If
' read json string from the file
strJSONString = ReadFromFile(WScript.Arguments(0), FileEncoding)
' parse json string
ParseJSON strJSONString, varJSON, strState
' check if root element is an array
If strState <> "Array" Then
CreateObject("WScript.Shell").PopUp "JSON root element is not an array", 3, , 48
WScript.Quit
End If
' you can place your own algorithm in this block
' currently it adds a property to each object in array
For i = 0 To UBound(varJSON)
If IsObject(varJSON(i)) Then ' check if the modified element is an object
varJSON(i).Add "item", i ' add property
End If
Next
' serialize json
strJSONString = SerializeJSON(varJSON)
' write json string to the file
WriteToFile strJSONString, WScript.Arguments(0), FileEncoding
CreateObject("WScript.Shell").PopUp "Completed", 1, , 64
Sub ParseJSON(ByVal strContent, varJSON, strState)
' strContent - source JSON string
' varJSON - created object or array to be returned as result
' strState - Object|Array|Error depending on processing to be returned as state
Dim objRegEx, refTokenize
Set refTokenize = GetRef("Tokenize")
Set objTokens = CreateObject("Scripting.Dictionary")
Set objRegEx = CreateObject("VBScript.RegExp")
With objRegEx
' specification http://www.json.org/
.Global = True
.MultiLine = True
.IgnoreCase = True
.Pattern = """(?:\\""|[^""])*""(?=\s*(?:,|\:|\]|\}))"
REM .Pattern = "1"
strTokenType = "str"
strContent = .Replace(strContent, refTokenize)
.Pattern = "(?:[+-])?(?:\d+\.\d*|\.\d+|\d+)e(?:[+-])?\d+(?=\s*(?:,|\]|\}))"
strTokenType = "num"
strContent = .Replace(strContent, refTokenize)
.Pattern = "(?:[+-])?(?:\d+\.\d*|\.\d+|\d+)(?=\s*(?:,|\]|\}))"
strTokenType = "num"
strContent = .Replace(strContent, refTokenize)
.Pattern = "\b(?:true|false|null)(?=\s*(?:,|\]|\}))"
strTokenType = "cst"
strContent = .Replace(strContent, refTokenize)
.Pattern = "\b[A-Za-z_]\w*(?=\s*\:)" ' unspecified name without quotes
strTokenType = "nam"
strContent = .Replace(strContent, refTokenize)
.Pattern = "\s"
strContent = .Replace(strContent, "")
.MultiLine = False
Do
bTokenMatched = False
.Pattern = "<\d+(?:str|nam)>\:<\d+(?:str|num|obj|arr|cst)>"
strTokenType = "prp"
strContent = .Replace(strContent, refTokenize)
.Pattern = "\{(?:<\d+prp>(?:,<\d+prp>)*)?\}"
strTokenType = "obj"
strContent = .Replace(strContent, refTokenize)
.Pattern = "\[(?:<\d+(?:str|num|obj|arr|cst)>(?:,<\d+(?:str|num|obj|arr|cst)>)*)?\]"
strTokenType = "arr"
strContent = .Replace(strContent, refTokenize)
Loop While bTokenMatched
.Pattern = "^<\d+(?:obj|arr)>$" ' unspecified top level array
If Not (.Test(strContent) And objTokens.Exists(strContent)) Then
varJSON = Null
strState = "Error"
Else
Retrieve objTokens, objRegEx, strContent, varJSON
If IsObject(varJSON) Then
strState = "Object"
Else
strState = "Array"
End If
End If
End With
End Sub
Function Tokenize(strMatch, lngPos, strSource)
' fn_replace(strMatch, strSubMatch1[, strSubMatch2[, strSubMatch3 ... ]], lngPos, strSource)
Tokenize = "<" & objTokens.Count & strTokenType & ">"
objTokens(Tokenize) = strMatch
bTokenMatched = True
End Function
Sub Retrieve(objTokens, objRegEx, strTokenKey, varTransfer)
Dim strContent, strType, objMatches, objMatch, strName, varValue, objArrayElts
strType = Left(Right(strTokenKey, 4), 3)
strContent = objTokens(strTokenKey)
With objRegEx
.Global = True
Select Case strType
Case "obj"
.Pattern = "<\d+\w{3}>"
Set objMatches = .Execute(strContent)
Set varTransfer = CreateObject("Scripting.Dictionary")
For Each objMatch In objMatches
Retrieve objTokens, objRegEx, objMatch.Value, varTransfer
Next
Case "prp"
.Pattern = "<\d+\w{3}>"
Set objMatches = .Execute(strContent)
Retrieve objTokens, objRegEx, objMatches(0).Value, strName
Retrieve objTokens, objRegEx, objMatches(1).Value, varValue
If IsObject(varValue) Then
Set varTransfer(strName) = varValue
Else
varTransfer(strName) = varValue
End If
Case "arr"
.Pattern = "<\d+\w{3}>"
Set objMatches = .Execute(strContent)
Set objArrayElts = CreateObject("Scripting.Dictionary")
For Each objMatch In objMatches
Retrieve objTokens, objRegEx, objMatch.Value, varValue
If IsObject(varValue) Then
Set objArrayElts(objArrayElts.Count) = varValue
Else
objArrayElts(objArrayElts.Count) = varValue
End If
Next
varTransfer = objArrayElts.Items
Case "nam"
varTransfer = strContent
Case "str"
varTransfer = Mid(strContent, 2, Len(strContent) - 2)
varTransfer = Replace(varTransfer, "\""", """")
varTransfer = Replace(varTransfer, "\\", "\")
varTransfer = Replace(varTransfer, "\/", "/")
varTransfer = Replace(varTransfer, "\b", Chr(8))
varTransfer = Replace(varTransfer, "\f", Chr(12))
varTransfer = Replace(varTransfer, "\n", vbLf)
varTransfer = Replace(varTransfer, "\r", vbCr)
varTransfer = Replace(varTransfer, "\t", vbTab)
.Global = False
.Pattern = "\\u[0-9a-fA-F]{4}"
Do While .Test(varTransfer)
varTransfer = .Replace(varTransfer, ChrW(("&H" & Right(.Execute(varTransfer)(0).Value, 4)) * 1))
Loop
Case "num"
varTransfer = Eval(strContent)
Case "cst"
Select Case LCase(strContent)
Case "true"
varTransfer = True
Case "false"
varTransfer = False
Case "null"
varTransfer = Null
End Select
End Select
End With
End Sub
Function SerializeJSON(varJSON)
Dim lngIndent
SerializeJSON = ""
lngIndent = 0
Traverse SerializeJSON, lngIndent, varJSON, vbTab, 1
End Function
Sub Traverse(strResult, lngIndent, varElement, strIndent, lngStep)
Dim strVarType, arrKeys, lngIndex, strTemp
strVarType = VarType(varElement)
Select Case True
Case strVarType = vbObject
If varElement.Count = 0 Then
strResult = strResult & "{}"
Else
strResult = strResult & "{" & vbCrLf
lngIndent = lngIndent + lngStep
arrKeys = varElement.Keys
For lngIndex = 0 To UBound(arrKeys)
strResult = strResult & String(lngIndent, strIndent) & """" & arrKeys(lngIndex) & """" & ": "
Traverse strResult, lngIndent, varElement(arrKeys(lngIndex)), strIndent, lngStep
If Not (lngIndex = UBound(arrKeys)) Then strResult = strResult & ","
strResult = strResult & vbCrLf
Next
lngIndent = lngIndent - lngStep
strResult = strResult & String(lngIndent, strIndent) & "}"
End If
Case strVarType >= vbArray
If UBound(varElement) = -1 Then
strResult = strResult & "[]"
Else
strResult = strResult & "[" & vbCrLf
lngIndent = lngIndent + lngStep
For lngIndex = 0 To UBound(varElement)
strResult = strResult & String(lngIndent, strIndent)
Traverse strResult, lngIndent, varElement(lngIndex), strIndent, lngStep
If Not (lngIndex = UBound(varElement)) Then strResult = strResult & ","
strResult = strResult & vbCrLf
Next
lngIndent = lngIndent - lngStep
strResult = strResult & String(lngIndent, strIndent) & "]"
End If
Case strVarType = vbInteger Or strVarType = vbLong
strResult = strResult & varElement
Case strVarType = vbSingle Or strVarType = vbDouble
strResult = strResult & Replace(varElement, ",", ".")
Case strVarType = vbNull
strResult = strResult & "Null"
Case strVarType = vbBoolean
If varElement Then
strResult = strResult & "True"
Else
strResult = strResult & "False"
End If
Case Else
strTemp = Replace(varElement, "\""", """")
strTemp = Replace(strTemp, "\", "\\")
strTemp = Replace(strTemp, "/", "\/")
strTemp = Replace(strTemp, Chr(8), "\b")
strTemp = Replace(strTemp, Chr(12), "\f")
strTemp = Replace(strTemp, vbLf, "\n")
strTemp = Replace(strTemp, vbCr, "\r")
strTemp = Replace(strTemp, vbTab, "\t")
strResult = strResult & """" & strTemp & """"
End Select
End Sub
Function ReadFromFile(strPath, intFormat)
With CreateObject("Scripting.FileSystemObject").OpenTextFile(strPath, 1, False, intFormat)
ReadFromFile = ""
If Not .AtEndOfStream Then ReadFromFile = .ReadAll
.Close
End With
End Function
Sub WriteToFile(strCont, strPath, intFormat)
With CreateObject("Scripting.FileSystemObject").OpenTextFile(strPath, 2, True, intFormat)
.Write(strCont)
.Close
End With
End Sub
Итак, сохраните этот скрипт как файл .vbs и выполните все шаги в моем ответе по приведенной выше ссылке.
Я проверил это на примере JSON:
[
{
"display": "HTML Tutorial",
"url": "http:\/\/www.w3schools.com\/html\/default.asp"
},
{
"display": "CSS Tutorial",
"url": "http:\/\/www.w3schools.com\/css\/default.asp"
},
{
"display": "JavaScript Tutorial",
"url": "http:\/\/www.w3schools.com\/js\/default.asp"
},
{
"display": "jQuery Tutorial",
"url": "http:\/\/www.w3schools.com\/jquery\/default.asp"
},
{
"display": "JSON Tutorial",
"url": "http:\/\/www.w3schools.com\/json\/default.asp"
},
{
"display": "AJAX Tutorial",
"url": "http:\/\/www.w3schools.com\/ajax\/default.asp"
},
{
"display": "SQL Tutorial",
"url": "http:\/\/www.w3schools.com\/sql\/default.asp"
},
{
"display": "PHP Tutorial",
"url": "http:\/\/www.w3schools.com\/php\/default.asp"
},
{
"display": "XML Tutorial",
"url": "http:\/\/www.w3schools.com\/xml\/default.asp"
}
]
После обработки свойство "item" появляется в каждом объекте массива. Обратите внимание, что исходная строка JSON сериализуется в соответствии со стандартом ECMA-404 "Стандарт обмена данными JSON", поэтому вы можете найти некоторые отличия от исходного форматирования.
[
{
"display": "HTML Tutorial",
"url": "http:\/\/www.w3schools.com\/html\/default.asp",
"item": 0
},
{
"display": "CSS Tutorial",
"url": "http:\/\/www.w3schools.com\/css\/default.asp",
"item": 1
},
{
"display": "JavaScript Tutorial",
"url": "http:\/\/www.w3schools.com\/js\/default.asp",
"item": 2
},
{
"display": "jQuery Tutorial",
"url": "http:\/\/www.w3schools.com\/jquery\/default.asp",
"item": 3
},
{
"display": "JSON Tutorial",
"url": "http:\/\/www.w3schools.com\/json\/default.asp",
"item": 4
},
{
"display": "AJAX Tutorial",
"url": "http:\/\/www.w3schools.com\/ajax\/default.asp",
"item": 5
},
{
"display": "SQL Tutorial",
"url": "http:\/\/www.w3schools.com\/sql\/default.asp",
"item": 6
},
{
"display": "PHP Tutorial",
"url": "http:\/\/www.w3schools.com\/php\/default.asp",
"item": 7
},
{
"display": "XML Tutorial",
"url": "http:\/\/www.w3schools.com\/xml\/default.asp",
"item": 8
}
]
Несмотря на то, что алгоритм добавления элементов жестко запрограммирован в сценарии, его можно легко расширить с помощью диалогового окна для параметров, установленных через облегченный графический интерфейс mshta
. Если этот подход соответствует вашим требованиям, то дайте мне знать, какие опции вы хотите реализовать в GUI, более сложные модификации и т.д.