Каковы хорошие инструменты CLI для JSON? - PullRequest
57 голосов
/ 29 мая 2010

Общая проблема

Несмотря на то, что я могу диагностировать основную причину события, определить, сколько пользователей оно затронуло, или извлечь журналы времени, чтобы оценить влияние недавнего изменения кода на производительность и пропускную способность, мои инструменты остаются прежними: grep , awk, sed, tr, uniq, sort, zcat, tail, head, join и split. Чтобы склеить их все вместе, Unix дает нам каналы, а для более сложной фильтрации у нас есть xargs. Если это подведет меня, всегда есть perl -e.

Эти инструменты идеально подходят для обработки файлов CSV, файлов с разделителями табуляции, файлов журналов с предсказуемым форматом строк или файлов с разделенными запятыми парами ключ-значение. Другими словами, файлы, в которых каждая строка не имеет контекста.

Аналоги XML

Недавно мне нужно было пройти через гигабайты XML, чтобы построить гистограмму использования пользователем. Это было достаточно просто с инструментами, которые у меня были, но для более сложных запросов нормальные подходы не работают. Скажем, у меня есть файлы с такими элементами:

<foo user="me">
    <baz key="zoidberg" value="squid" />
    <baz key="leela"    value="cyclops" />
    <baz key="fry"      value="rube" />
</foo>

И скажем, я хочу создать отображение от пользователя до среднего числа <baz> с на <foo>. Обработка построчно больше не является опцией: мне нужно знать, какого пользователя <foo> я сейчас проверяю, чтобы знать, чье среднее значение для обновления. Любая разновидность Unix one liner, которая выполняет эту задачу, вероятно, будет непостижимой.

К счастью, в XML-стране у нас есть замечательные технологии, такие как XPath, XQuery и XSLT, чтобы помочь нам.

Раньше я привык к использованию замечательного XML::XPath модуля Perl для выполнения запросов, подобных приведенному выше, но после нахождения плагина TextMate, который мог бы запустить выражение XPath для моего текущего окна , я перестал писать одноразовые скрипты Perl для запроса XML. И я только что узнал о XMLStarlet , который устанавливается при наборе этого текста и который я с нетерпением жду в будущем.

Решения JSON?

Так что это подводит меня к моему вопросу: есть ли такие инструменты для JSON? Это всего лишь вопрос времени, когда какая-то задача расследования потребует от меня выполнения аналогичных запросов к файлам JSON, и без таких инструментов, как XPath и XSLT, такая задача будет намного сложнее. Если бы у меня была связка JSON, которая выглядела бы так:

{
  "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" }
  ]
}

И я хотел узнать среднее количество телефонных номеров, которое имел каждый человек, я мог сделать что-то подобное с XPath:

fn:avg(/fn:count(phoneNumber))

Вопросы

  1. Есть ли инструменты командной строки которые могут "запрашивать" файлы JSON в этом способ
  2. Если вам нужно обработать кучу JSON-файлы в командной строке Unix, какие инструменты вы используете?
  3. Черт, есть ли работа, которая делается сделать такой язык запросов для JSON?
  4. Если вы используете такие инструменты в ваша повседневная работа, что вы нравится / не нравится в них? Здесь есть какие-нибудь ошибки?

Я заметил, что все больше сериализации данных выполняется с использованием JSON, поэтому такие инструменты обработки будут иметь решающее значение при анализе больших дампов данных в будущем. Языковые библиотеки для JSON очень сильны, и достаточно просто написать сценарии для такой обработки, но для того, чтобы люди действительно могли поиграть с инструментами оболочки данных, необходимы.

Смежные вопросы

Ответы [ 8 ]

51 голосов
/ 03 января 2013

Я только что нашел это:

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

"jq - это легкий и гибкий процессор командной строки JSON."

2014 обновление:

@ user456584 упомянуто:

Также есть команда json (например, jsontool). Я склонен предпочесть это JQ. Очень UNIX-й. Вот ссылка на проект: github.com/trentm/json -

в json README в http://github.com/trentm/json имеется длинный список похожих вещей

7 голосов
/ 17 апреля 2012

Я создал модуль, специально разработанный для манипулирования JSON из командной строки:

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

image

  • FLEXIBLE - инструмент «швейцарский армейский нож» для обработки данных JSON - можно использовать как простой принтер-красавчик или как полнофункциональную командную строку Javascript
  • МОЩНЫЙ - предоставляет всю мощь и функциональность underscore.js (плюс underscore.string)
  • SIMPLE - упрощает написание однострочников JS, аналогично использованию "perl -pe"
  • CHAINED - Несколько вызовов команд могут быть объединены в цепочку для создания конвейера обработки данных
  • МУЛЬТИ-ФОРМАТ - Богатая поддержка форматов ввода / вывода - красивая печать, строгий 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. Я разработал довольно обширный набор функций, но я был бы рад расставить приоритеты для функций, которые необходимы членам сообщества.

5 голосов
/ 29 мая 2010

Один из способов сделать это - преобразовать его в XML. Далее используются два модуля Perl (JSON и XML :: Simple) для конвертации данных:

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>
4 голосов
/ 03 июня 2011

Взгляните на этот безумный проект jsawk . Это дизайн для фильтрации через JSON-ввод из командной строки. Проверьте также resty для клиента REST командной строки, который можно использовать в конвейерах, которые могут пригодиться.

3 голосов
/ 31 мая 2010

Недавно я обнаружил, что JSON легко может быть eval -обработан с Python:

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

Хотя метод, очевидно, завершится ошибкой, если вход JSON содержит нули.

2 голосов
/ 29 мая 2010

Взгляните на f:json-document() из библиотеки FXSL 2.x .

Используя эту функцию, очень легко включить 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>
1 голос
/ 29 июня 2019

К счастью, в XML-стране у нас есть замечательные технологии, такие как XPath, XQuery и XSLT, чтобы помочь нам.
[...]
Так что это приводит меня к моему вопросу: есть ли такие инструменты для JSON?

Если вы спросите меня, Xidel это именно то, что вы ищете.

Xidel - это инструмент командной строки для загрузки и извлечения данных из страниц HTML / XML или JSON-API с использованием CSS, XPath 3.0, XQuery 3.0, JSONiq или шаблонных шаблонов. Он также может создавать новые или преобразованные документы XML / HTML / JSON.

Запрос:

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

или

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

Выход:

2
0 голосов
/ 03 ноября 2018

Существует также интерактивный инструмент терминала - fx

Передача в FX любого JSON и анонимная функция для его уменьшения.

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

Запустить интерактивный режим без передачи аргументов:

$ curl ... | fx

image

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...