在写入文件之前格式化curl输出

时间:2015-11-19 07:32:11

标签: json batch-file curl format output

我使用curl(7.39.0)调用REST Web服务并将响应写入.json文件。

以下是我的称呼方式

curl -L-X POST -b cookies.txt -H "Content-Type: application/json" http://localhost:7001/web/service/url -d {"param1":"value1"} -o "C:\output\serviceName.json" 

响应被写入输出文件,但没有格式化。

{"status": "success","user": "name", "regId": "14420","subscriber": [{"memberFor":"3 years","lastLogin":"2 days ago"}]}

我的问题是:

a / 有没有办法在将json响应写入输出文件之前对其进行格式化(如下所示)?

{
        "status": "success",
        "user": "name",
        "regId": "14420"
        "subscriber": [
            {
                "memberFor":"3 years",
                "lastLogin":"2 days ago"     
            }
        ]
    }

b / 如果无法通过cURL进行格式化,我希望编写一个简单的批处理文件来自动打开json输出文件并应用格式。像

这样的东西
@echo off
cls
"C:\Program Files\Notepad++\notepad++"   "C:\output\serviceName.json" 
pause

MS-BATCH中是否有可用的标志/选项来实现此目的?

由于

3 个答案:

答案 0 :(得分:1)

编辑我找到了使用htmlfile COM对象的解决方案,该对象应该提供最快的性能(至少对于单次运行)并且不需要Internet连接。请参阅本答复中的最后一个解决方案。

因为您使用[batch-file]标记标记了这个问题,并且因为我发现挑战很有趣,所以我编写了一个混合批处理+ JScript脚本,它将美化您的JSON。从JScript 5.7 doesn't natively support the JSON object开始,此脚本使用外部json2.js,如果尚未下载,则通过XHR下载。从那里开始,调用JavaScript熟悉的JSON.stringify()方法及其美化选项很简单。

语法:

json_generator | batfile.bat
    -or-
batfile.bat < jsonfile.json

使用示例:

beautify.bat < "C:\output\serviceName.json" > "C:\output\beautified.json"

这导致以下内容保存为beautified.json:

{  
        "status": "success",
        "user": "name",
        "regId": "14420",
        "subscriber": [
                {
                        "memberFor": "3 years",
                        "lastLogin": "2 days ago"
                }
        ]
}

代码:

@if (@CodeSection == @Batch) @then

@echo off & setlocal

cscript /nologo /e:JScript "%~f0"
goto :EOF

@end // end Batch / begin JScript hybrid chimera

var xObj = WSH.CreateObject('Microsoft.XMLHTTP'),
    fso = WSH.CreateObject('Scripting.FileSystemObject'),
    temp = WSH.CreateObject('WScript.Shell').Environment('Process')('temp'),
    j2lib = 'https://raw.githubusercontent.com/douglascrockford/JSON-js/master/json2.js',
    json = WSH.StdIn.ReadAll();

if (fso.FileExists(temp + '\\json2.js')) {
    j2lib = fso.OpenTextFile(temp + '\\json2.js', 1);
    eval(j2lib.ReadAll());
    j2lib.Close();
}
else {
    with (xObj) {
        open("GET", j2lib, true);
        setRequestHeader('User-Agent', 'XMLHTTP/1.0');
        send('');
    }

    while (xObj.readyState != 4) WSH.Sleep(50);
    eval(xObj.responseText);
    j2lib = fso.CreateTextFile(temp + '\\json2.js', true);
    j2lib.Write(xObj.responseText);
    j2lib.Close();
}

WSH.Echo(JSON.stringify(JSON.parse(json), null, '\t'));

这是使用相同语法的另一种解决方案,不需要下载json2.js。它通过无形地启动Internet Explorer,调用IE的内置JSON方法,然后再次静默关闭IE来避免这种情况。这很可能比上面的方法慢,并且可以根据机器安全策略阻止它;但它确实具有在没有互联网连接的情况下工作的优势。

@if (@CodeSection == @Batch) @then

@echo off & setlocal

cscript /nologo /e:JScript "%~f0"
goto :EOF

@end // end Batch / begin JScript hybrid chimera

var IE = WSH.CreateObject('InternetExplorer.Application'),
    json = WSH.StdIn.ReadAll();

IE.Visible = 0;
IE.Navigate('about:blank');
while (IE.Busy || IE.ReadyState != 4) WSH.Sleep(25);

var JSON = IE.document.parentWindow.JSON,
    pretty = JSON.stringify(JSON.parse(json), null, "\t");

WSH.Echo(pretty);

IE.Quit();
try { while (IE && IE.Busy) WSH.Sleep(25); }
catch(e) {}

这是另一个解决方案,这次使用批处理/ HTA混合。有<meta>标签强制HTA解释器进入IE9兼容性,因此包括 支持JSON方法。这比IE方法快,但不是完全不可见的。 HTA窗口在屏幕上闪烁一瞬间,然后自行关闭。

<!-- : batch portion

@echo off & setlocal

rem // The for /f loop forces mshta to communicate with stdout
rem // as a console script host.  Without for /f, attempting
rem // to write to stdout results in an invalid handle error.
for /f "delims=" %%I in ('mshta.exe "%~f0"') do echo(%%I
goto :EOF

end batch / begin HTA : -->

<meta http-equiv="x-ua-compatible" content="IE=9" />
<script>
var fso = new ActiveXObject('Scripting.FileSystemObject'),
    stdin = fso.GetStandardStream(0),
    stdout = fso.GetStandardStream(1),
    json = stdin.ReadAll(),
    pretty = JSON.stringify(JSON.parse(json), null, '\t');

close(stdout.Write(pretty));
</script>

我认为最好的解决方案是使用scantily-documented htmlfile COM对象。使用与<meta>标记相同的技巧强制它进入IE9兼容性,如上面的HTA解决方案所示,htmlfile COM对象提供对JSON方法的本机支持,无需库下载,也不需要分叉一个额外的窗口助手应用程序。它只是加载一个DLL。

@if (@CodeSection == @Batch) @then

@echo off & setlocal

cscript /nologo /e:JScript "%~f0"
goto :EOF

@end // end batch / begin JScript hybrid chimera

var htmlfile = WSH.CreateObject('htmlfile'),
    json = WSH.StdIn.ReadAll();

htmlfile.write('<meta http-equiv="x-ua-compatible" content="IE=9" />');

var JSON = htmlfile.parentWindow.JSON,
    pretty = JSON.stringify(JSON.parse(json), null, '\t');

htmlfile.close(WSH.Echo(pretty));

答案 1 :(得分:0)

只是对旧问题的更新。 https://stedolan.github.io/jq/是非常好的工具。默认情况下,jq漂亮打印JSON输出。所以你可以做到

curl ... | jq .

“”。是身份过滤器。见https://stedolan.github.io/jq/manual/#Invokingjq

答案 2 :(得分:0)

我相信,Xidel都可以完成此操作,默认情况下,它会打印出漂亮的照片:

import random as rnd
import generator as gtr
import treeOperations as trop

class Generation(object):
    def __init__(self):
      self.membersWithErrors = []

    def addMember(self, member):
      """ Add a tree to the generation """
      self.membersWithErrors.append([member, 0])

    def setMember(self, member, index):
      """ Updates the member at the specified position """
      self.membersWithErrors[index] = member

    def setError(self, index, error):
      """ Sets the error of the member at the specified position """
      self.membersWithErrors[index][1] = error

    def getMember(self, index):
      """ Returns the member at the specified position """
      return self.membersWithErrors[index][0]

    def getError(self, index):
      """ Returns the error of the member at the specified position """
      return self.membersWithErrors[index][1]

    def size(self):
      """ Returns the number of members curently in the generation """
      return len(self.membersWithErrors)

    def clear(self):
      """ Clears the generation, i.e. removes all the members """
      self.membersWithErrors.clear()

    def sort(self, descending):
      """ Sorts the members of the generation according the their score """
      self.membersWithErrors.sort(key = lambda l: l[1], reverse = descending)

    ########## YOU HAVE TO FIX THIS TOO ############
    def getMembersForReproduction(self, numMembers, pickProb):
        """ Returns a certain number of distinct members from the generation.
        The first member is selected with probability pickProb. If it's not chosen, the 
        second member is selected with probability pickProb, and so on. """
        selectedMembers = []
        while len(selectedMembers) < numMembers: 
          indexSelected = 0  
          while rnd.randint(0, 100) > int(pickProb * 100) and indexSelected != len(self.membersWithErrors) - 1:
        indexSelected += 1
        memberWithErrorSelected = self.membersWithErrors[indexSelected]
        if memberWithErrorSelected[0] not in selectedMembers:
           selectedMembers.append(memberWithErrorSelected[0])
        return selectedMembers

    ############ This is the proper identation #############
    def next(self, crossoverPerc, mutationPerc, randomPerc, copyPerc, shouldPruneForMaxHeight, minHeight, maxHeight, minValue, maxValue, variables, operators):
        """ It proceeds to the next generation with the help of genetic operations """
        oldMembersWithError = self.membersWithErrors
        newMembersWithError = []
        maxMembers = len(oldMembersWithError)

        numCrossover = int(maxMembers * crossoverPerc)
        numMutation = int(maxMembers * mutationPerc)
        numRandom = int(maxMembers * randomPerc)
        numCopy = maxMembers - numCrossover - numMutation - numRandom

        # Crossover
        for i in range(0, numCrossover):
        members = self.getMembersForReproduction(2, 0.3)
        m1 = members[0]
        m2 = members[1]
        newMember = trop.crossover(m1, m2)
        newMembersWithError.append([newMember, 0])

        # Crossover
        for i in range(0, numCrossover):
        members = self.getMembersForReproduction(2, 0.3)
        m1 = members[0]
        m2 = members[1]
        newMember = trop.crossover(m1, m2)
        if shouldPruneForMaxHeight and newMember.height() > maxHeight:
           newMember = trop.pruneTreeForMaxHeight(newMember, maxHeight, minValue, maxValue, variables)
        newMembersWithError.append([newMember, 0])

        # Mutation
        for i in range(0, numMutation):
            m1 = self.getMembersForReproduction(1, 0.3)[0]
            newMembersWithError.append([trop.mutation(m1, minValue, maxValue, variables, operators), 0])

        # Random
        for i in range(0, numRandom):
        newMembersWithError.append([gtr.getTree(minHeight, maxHeight, minValue, maxValue, variables, operators), 0])

        # Copy
        members = self.getMembersForReproduction(numCopy, 0.3)
        for m in members:
            ewMembersWithError.append([m.clone(), 0])

        self.membersWithErrors = newMembersWithError

预期输出:

xidel -s --method=POST ^
--load-cookies="cookies.txt" ^
-H "Content-Type: application/json" ^
-d {"param1":"value1"} ^
http://localhost:7001/web/service/url ^
-e "$json"