什么是JSON的良好CLI工具?

时间:2010-05-28 23:34:44

标签: json xslt command-line xpath

一般问题

虽然我可能正在诊断事件的根本原因,确定它影响了多少用户,或者为了评估最近代码更改的性能和吞吐量影响而提取时序日志,但我的工具保持不变:{{1 }},grepawksedtruniqsortzcattailheadjoin。为了将它们粘合在一起,Unix为我们提供了管道,对于更高级的过滤,我们有split。如果这些都让我失望,那么总是xargs

这些工具非常适合处理CSV文件,制表符分隔文件,具有可预测行格式的日志文件或具有逗号分隔键值对的文件。换句话说,每行都没有上下文的文件。

XML类似物

我最近需要浏览千兆字节的XML来构建用户的直方图。使用我的工具这很容易,但对于更复杂的查询,正常方法会中断。假设我的文件包含以下内容:

perl -e

让我们说我想要生成一个从用户到<foo user="me"> <baz key="zoidberg" value="squid" /> <baz key="leela" value="cyclops" /> <baz key="fry" value="rube" /> </foo> <baz>个平均数的映射。逐行处理不再是一种选择:我需要知道我正在检查哪个用户<foo>,所以我知道要更新的平均值。完成这项任务的任何类型的Unix一行都可能是不可理解的。

幸运的是,在XML-land中,我们有很多精彩的技术,如XPath,XQuery和XSLT来帮助我们。

以前,我已经习惯使用精彩的<foo> Perl模块来完成上面的查询,但在找到TextMate Plugin that could run an XPath expression against my current window后,我停止编写一次性Perl脚本来查询XML。我刚刚发现了XMLStarlet正在安装的内容,因为我输入了这个,并且我期待将来使用它。

JSON解决方案?

所以这引出了我的问题:JSON有没有这样的工具?一些调查任务要求我对JSON文件进行类似的查询只是时间问题,并且没有像XPath和XSLT这样的工具,这样的任务将会困难得多。如果我有一堆看起来像这样的JSON:

XML::XPath

想找到每个人的平均电话号码,我可以用XPath做这样的事情:

{
  "firstName": "Bender",
  "lastName": "Robot",
  "age": 200,
  "address": {
    "streetAddress": "123",
    "city": "New York",
    "state": "NY",
    "postalCode": "1729"
  },
  "phoneNumber": [
    { "type": "home", "number": "666 555-1234" },
    { "type": "fax", "number": "666 555-4567" }
  ]
}

问题

  1. 是否有任何命令行工具 这可以“查询”JSON文件 方式是什么?
  2. 如果你必须处理一堆 Unix命令行上的JSON文件, 你用什么工具?
  3. 哎呀,甚至有工作要做 制作这样的查询语言 对于JSON?
  4. 如果您确实使用了这样的工具 你的日常工作,你是什么 喜欢/不喜欢他们?在那儿 任何陷阱?
  5. 我注意到越来越多的数据序列化正在使用JSON完成,因此在将来分析大型数据转储时,这样的处理工具将至关重要。 JSON的语言库非常强大,编写脚本以进行这种处理非常容易,但真正让人们玩数据shell工具是必需的。

    相关问题

8 个答案:

答案 0 :(得分:51)

我刚刚发现了这个:

http://stedolan.github.com/jq/

“jq是一个轻量级且灵活的命令行JSON处理器。”

2014年更新:

@ user456584提到:

  

还有'json'命令(例如'jsontool')。我倾向于喜欢它而不是jq。很UNIX-y。这是该项目的链接:github.com/trentm/json -

http://github.com/trentm/jsonjson 自述文件中有一长串相似的内容

  

答案 1 :(得分:7)

我创建了一个专门用于命令行JSON操作的模块:

https://github.com/ddopson/underscore-cli

  • 灵活 - 用于处理JSON数据的“瑞士军刀”工具 - 可以用作简单的漂亮打印机,也可以用作全功能的Javascript命令行
  • 强大 - 公开underscore.js的全部功能和功能(加上underscore.string)
  • SIMPLE - 使用类似于“perl -pe”的JS单行编写简单
  • CHAINED - 可以将多个命令调用链接在一起以创建数据处理管道
  • MULTI-FORMAT - 对输入/输出格式的丰富支持 - 漂亮的打印,严格的JSON等[即将推出]
  • DOCUMENTED - 出色的命令行文档,每个命令都有多个示例

它可以让你轻松地做强大的事情:

cat earthporn.json | underscore select '.data .title'
# [ 'Fjaðrárgljúfur canyon, Iceland [OC] [683x1024]',
#   'New town, Edinburgh, Scotland [4320 x 3240]',
#   'Sunrise in Bryce Canyon, UT [1120x700] [OC]',
# ...
#   'Kariega Game Reserve, South Africa [3584x2688]',
#   'Valle de la Luna, Chile [OS] [1024x683]',
#   'Frosted trees after a snowstorm in Laax, Switzerland [OC] [1072x712]' ]

cat earthporn.json | underscore select '.data .title' | underscore count
# 25

underscore map --data '[1, 2, 3, 4]' 'value+1'
# prints: [ 2, 3, 4, 5 ]

underscore map --data '{"a": [1, 4], "b": [2, 8]}' '_.max(value)'
# [ 4, 8 ]

echo '{"foo":1, "bar":2}' | underscore map -q 'console.log("key = ", key)'
# key = foo
# key = bar

underscore pluck --data "[{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}]" name
# [ 'moe', 'larry', 'curly' ]

underscore keys --data '{name : "larry", age : 50}'
# [ 'name', 'age' ]

underscore reduce --data '[1, 2, 3, 4]' 'total+value'
# 10

它有一个非常好的命令行帮助系统,非常灵活。经过充分测试,可随时使用;但是,我仍然在构建一些功能,比如输入/输出格式的替代品,以及我的模板处理工具中的合并(参见TODO.md)。如果您有任何功能请求,请对此帖子发表评论或在github中添加问题。我设计了一个非常广泛的功能集,但我很乐意优先考虑社区成员所需的功能。

答案 2 :(得分:5)

您可以做的一种方法是将其转换为XML。以下使用两个perl模块(JSON和XML :: Simple)来执行fly-by转换:

cat test.json | perl -MJSON -MXML::Simple -e 'print XMLout(decode_json(do{local$/;<>}),RootName=>"json")'

对于你的例子json最终为:

<json age="200" firstName="Bender" lastName="Robot">
  <address city="New York" postalCode="1729" state="NY" streetAddress="123" />
  <phoneNumber number="666 555-1234" type="home" />
  <phoneNumber number="666 555-4567" type="fax" />
</json>

答案 3 :(得分:4)

看看这个疯狂的项目jsawk。设计是从命令行过滤JSON输入。检查resty以及可以派上用场的管道中使用的命令行REST客户端。

答案 4 :(得分:3)

最近我发现JSON很容易被eval - 用Python编写:

$ python -c "json=eval(open('/json.txt').read()); print len(json['phoneNumber'])"
2

虽然如果JSON输入包含空值,该方法显然会失败。

答案 5 :(得分:2)

查看f:json-document()中的FXSL 2.x library

使用此函数非常容易合并JSon并将其用作... XML。

例如,可以编写以下XPath表达式:

f:json-document($vstrParam)/Students/*[sex = 'Female']

Students的所有孩子都拥有sex = 'Female'

以下是完整示例:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:f="http://fxsl.sf.net/"
 exclude-result-prefixes="f xs"
 >
 <xsl:import href="../f/func-json-document.xsl"/>

 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vstrParam" as="xs:string">
{

  "teacher":{
    "name":
      "Mr Borat",
    "age":
      "35",
    "Nationality":
      "Kazakhstan"
             },


  "Class":{
    "Semester":
      "Summer",
    "Room":
      null,
    "Subject":
      "Politics",
    "Notes":
      "We're happy, you happy?"
           },

  "Students":
    {
      "Smith":
        {"First Name":"Mary","sex":"Female"},
      "Brown":
        {"First Name":"John","sex":"Male"},
      "Jackson":
        {"First Name":"Jackie","sex":"Female"}
    }
    ,


  "Grades":

    {
      "Test":
      [
        {"grade":"A","points":68,"grade":"B","points":25,"grade":"C","points":15},

        {"grade":"C","points":2, "grade":"B","points":29, "grade":"A","points":55},

        {"grade":"C","points":2, "grade":"A","points":72, "grade":"A","points":65}
       ]
    }


}
 </xsl:variable>

 <xsl:template match="/">
    <xsl:sequence select=
     "f:json-document($vstrParam)/Students/*[sex = 'Female']"/>

 </xsl:template>
</xsl:stylesheet>

当对任何XML文档应用上述转换(忽略)时,会生成正确的结果

<Smith>
   <First_Name>Mary</First_Name>
   <sex>Female</sex>
</Smith>
<Jackson>
   <First_Name>Jackie</First_Name>
   <sex>Female</sex>
</Jackson>

答案 6 :(得分:1)

  

幸运的是,在XML领域,我们拥有诸如XPath,XQuery和XSLT之类的出色技术来帮助我们。
  [...]
  所以这引出了我的问题:是否有类似JSON的工具?

如果您问我,Xidel正是您想要的。

  

Xidel是一个命令行工具,可以使用CSS,XPath 3.0,XQuery 3.0,JSONiq或模式模板从HTML / XML页面或JSON-API下载和提取数据。它还可以创建新的或转换后的XML / HTML / JSON文档。

查询:

xidel -s "input.json" \
-e '
  $json/avg(
    count(
      (phoneNumber)()
    )
  )
'

xidel -s "input.json" -e '$json/avg(count((phoneNumber)()))'

输出:

2

答案 7 :(得分:0)

还有交互式终端工具-fx

将任何JSON和匿名函数放入fx中以进行简化。

$ echo '{...}' | fx [code ...]

在不传递任何参数的情况下启动交互模式:

$ curl ... | fx