如何在批处理中解析简单的JSON字符串?
例如,如果有以下JSON字符串:
{ "...":"...", "year":2016, "time":"05:01", "...":"...", }
这个JSON字符串有许多元素,其中两个是“year”和“time”。我想从这个字符串中提取“year”和“time”的值,并将它们存储在两个变量中,而不使用任何外部库(即,我不想安装或下载任何用于此目的的外部工具,一个新安装的Windows应该具备所有必要的工具来执行此操作)。
如何在批处理中解析简单的JSON字符串?
例如,如果有以下JSON字符串:
{ "...":"...", "year":2016, "time":"05:01", "...":"...", }
这个JSON字符串有许多元素,其中两个是“year”和“time”。我想从这个字符串中提取“year”和“time”的值,并将它们存储在两个变量中,而不使用任何外部库(即,我不想安装或下载任何用于此目的的外部工具,一个新安装的Windows应该具备所有必要的工具来执行此操作)。
@echo off
setlocal
set string={ "other": 1234, "year": 2016, "value": "str", "time": "05:01" }
rem Remove quotes
set string=%string:"=%
rem Remove braces
set "string=%string:~2,-2%"
rem Change colon+space by equal-sign
set "string=%string:: ==%"
rem Separate parts at comma into individual assignments
set "%string:, =" & set "%"
echo other="%other%"
echo year="%year%"
echo value="%value%"
echo time="%time%"
输出:
other="1234"
year="2016"
value="str"
time="05:01"
这种方法的一个小不便是“时间”批处理动态变量将被新的JSON替换,但如果您使用setlocal
命令,这一点就不会造成任何问题。
编辑:只是为了完成cz3ch的请求,将结果放入“字符串”数组而不是将它们放在单独的变量中:
@echo off
setlocal
set string={ "other": 1234, "year": 2016, "value": "str", "time": "05:01" }
rem Remove quotes
set string=%string:"=%
rem Remove braces
set "string=%string:~2,-2%"
rem Change colon+space by "]equal-sign"
set "string=%string:: =]=%"
rem Separate parts at comma into individual array assignments
set "string[%string:, =" & set "string[%"
set string[
set "string=%string:~1,-1%"
,还从 set "string=%string::==%"
和 set "%string:,=" & set "%
中删除了空格。这应该是一个答案,因为不需要额外的工具(如 poweshell 或 jq)。 - oleksa这是一个混合的批处理和PowerShell解决方案。 PowerShell将JSON文本对象化(反序列化)并以键=值格式输出,以便于批处理中的for /f
循环捕获并设置为批处理变量。将此保存为.bat文件并尝试运行。
<# : batch portion (contained within a PowerShell multi-line comment)
@echo off & setlocal
set "JSON={ "year": 2016, "time": "05:01" }"
rem # re-eval self with PowerShell and capture results
for /f "delims=" %%I in ('powershell "iex (${%~f0} | out-string)"') do set "%%~I"
rem # output captured results
set JSON[
rem # end main runtime
goto :EOF
: end batch / begin PowerShell hybrid code #>
add-type -AssemblyName System.Web.Extensions
$JSON = new-object Web.Script.Serialization.JavaScriptSerializer
$obj = $JSON.DeserializeObject($env:JSON)
# output object in key=value format to be captured by Batch "for /f" loop
foreach ($key in $obj.keys) { "JSON[{0}]={1}" -f $key, $obj[$key] }
如果您只需要年份和时间值,只需使用%JSON[year]%
或%JSON[time]%
。
如果您从一个.json文件中读取JSON,您可以让PowerShell部分读取该文件,并将($env:JSON)
替换为((gc jsonfile.json))
。这样,您就不必依赖于JSON是多行和美化还是压缩。无论哪种方式,它都将被反序列化为相同的对象。
如果执行速度是一个问题,您可能更喜欢一个批处理+JScript混合解决方案。它将JSON反序列化为对象,与PowerShell解决方案相同,但是从批处理上下文调用JScript比从批处理调用PowerShell命令或脚本更快。
@if (@CodeSection == @Batch) @then
@echo off & setlocal
set "JSON={ "year": 2016, "time": "05:01" }"
rem // re-eval self with JScript interpreter and capture results
for /f "delims=" %%I in ('cscript /nologo /e:JScript "%~f0"') do set "%%~I"
rem // output captured results
set JSON[
rem // end main runtime
goto :EOF
@end // end Batch / begin JScript hybrid code
var htmlfile = WSH.CreateObject('htmlfile'),
txt = WSH.CreateObject('Wscript.Shell').Environment('process').Item('JSON');
htmlfile.write('<meta http-equiv="x-ua-compatible" content="IE=9" />');
var obj = htmlfile.parentWindow.JSON.parse(txt);
htmlfile.close();
for (var i in obj) WSH.Echo('JSON[' + i + ']=' + obj[i]);
与第一个 PowerShell 混合解决方案一样,如果你希望的话,可以通过在 JScript 部分从 .json 文件中读取来解析多行 JSON(通过创建 Scripting.FileSystemObject
对象并调用其 .OpenTextFile()
和 .ReadAll()
方法)。
这是另一个纯批处理方案,但它将 key=value 对设置为关联数组以避免像 Aacini 的解决方案一样覆盖 %time%
。我真的认为最好将 JSON 解析为辅助语言中的对象,而不是在纯批处理中作为平面文本解析,但我也意识到最佳答案并不总是最受欢迎的。
@echo off
setlocal
set "JSON={ "other": 1234, "year": 2016, "value": "str", "time": "05:01" }"
set "JSON=%JSON:~1,-1%"
set "JSON=%JSON:":=",%"
set mod=0
for %%I in (%JSON%) do (
set /a mod = !mod
setlocal enabledelayedexpansion
if !mod! equ 0 (
for %%# in ("!var!") do endlocal & set "JSON[%%~#]=%%~I"
) else (
endlocal & set "var=%%~I"
)
)
set JSON[
@echo off
set string={ "year": 2016, "time": "05:01" }
set string=%string:"=%
for /f "tokens=3,5" %%a in ('echo %string%') do set d=%%a&set t=%%b
echo -%d%- -%t%-
pause & goto :EOF
这是第二个:
@echo off
set string={ "year": 2016, "time": "05:01" }
for /f "tokens=3,5" %%a in ('echo %string%') do set d=%%~a&set t=%%~b
echo -%d%- -%t%-
pause & goto :EOF
使用https://stedolan.github.io/jq/,无需在批处理中使用powershell或字符串操作。
从JSON字符串获取字段值的示例:
set "year={ "other": 1234, "year": 2016, "value": "str", "time": "05:01" } | jq .year"
echo %year%
给你2016年
for /f "tokens=* delims=" %%a in ('jsonextractor.bat simple.json year') do set "year=%%~a"
for /f "tokens=* delims=" %%a in ('jsonextractor.bat simple.json time') do set "time_=%%~a"
echo %year% -- %time_%
ConvertFrom-Json
仅适用于PowerShell 3.0+。大多数Win 7框(无论我使用过哪个)默认为PowerShell 2.0,这使得使用该cmdlet部署脚本对许多最终用户具有问题。尽管如此,创建一个System.Web.Script.Serialization.JavaScriptSerializer
对象只需要几行额外的代码。 - rojo