Как я могу назначить и проанализировать вывод json-объекта из сценария [duplicate]

Это делается путем делегирования событий. Событие будет привязываться к элементу-оболочке, но будет делегировано элементу селекторного класса. Вот как это работает.

$('.wrapper-class').on("click", '.selector-class', function() {
    // Your code here
});

Примечание:

Элемент-оболочка-оболочка может быть любым ex. документа, тела или вашей обертки. Упаковщик должен уже существовать.

590
задан codeforester 8 March 2017 в 07:15
поделиться

30 ответов

Существует ряд инструментов, специально предназначенных для управления JSON из командной строки, и будет намного проще и надежнее, чем делать с Awk, например jq :

curl -s 'https://api.github.com/users/lambda' | jq -r '.name'

Вы также можете сделать это с помощью инструментов, которые, вероятно, уже установлены в вашей системе, например Python, с помощью модуля json , и поэтому избегайте любых дополнительных зависимостей, в то время как по-прежнему пользуясь надлежащим парсером JSON. Далее предполагается, что вы хотите использовать UTF-8, который должен быть закодирован в оригинальном JSON, и это то, что используют большинство современных терминалов:

Python 2:

export PYTHONIOENCODING=utf8
curl -s 'https://api.github.com/users/lambda' | \
    python -c "import sys, json; print json.load(sys.stdin)['name']"

Python 3:

curl -s 'https://api.github.com/users/lambda' | \
    python3 -c "import sys, json; print(json.load(sys.stdin)['name'])"

Исторические заметки

Этот ответ первоначально рекомендовал jsawk , который все равно должен работать, но немного более громоздким в использовании, чем jq и зависит от установленного автономного интерпретатора JavaScript, который менее распространен, чем интерпретатор Python, поэтому предпочтительные ответы, вероятно, предпочтительнее:

curl -s 'https://api.github.com/users/lambda' | jsawk -a 'return this.name'

Этот ответ также изначально использовал API Twitter из вопроса, но этот API больше не работает, что затрудняет копирование примеров для тестирования, а новый API Twitter требует API-ключей, поэтому я переключился на использование API GitHub, который можно легко использовать без ключей API. Первый ответ на исходный вопрос:

curl 'http://twitter.com/users/username.json' | jq -r '.text'
626
ответ дан Brian Campbell 18 August 2018 в 08:22
поделиться
  • 1
    Я не хотел добавлять зависимости к проекту, поэтому я хочу использовать sed / awk / curl, но jsawk кажется, что это самый «надежный». решение. – auser 24 December 2009 в 22:28
  • 2
    @ari Я не уверен, какой * nix-вкус вы используете, но Python является частью спецификации LSB (стандартная база Linux), которая сегодня должна охватывать большинство дистрибутивов. – Evan Plaice 28 February 2011 в 11:18
  • 3
    == & GT; Установка зависимостей для jsawk: nspr, spidermonkey – Jason 20 August 2014 в 19:53
  • 4
    потому что он запускает spidermonkey каждый раз, jsawk действительно медленный, когда вам нужно многократно его вызывать. jq - хорошая альтернатива – thrau 28 February 2016 в 20:20
  • 5
    @thrau +1. jq он доступен в репозитории и очень прост в использовании, поэтому он намного лучше, чем jsawk. Я тестировал оба в течение нескольких минут, jq выиграл эту битву – Szymon Sadło 17 June 2016 в 09:51

Двухстрочный, который использует python. Он работает особенно хорошо, если вы пишете один файл .sh, и вы не хотите зависеть от другого .py-файла. Он также использует использование трубы |. echo "{\"field\": \"value\"}" можно заменить чем-либо, печатающим json на stdout.

echo "{\"field\": \"value\"}" | python -c 'import sys, json
print(json.load(sys.stdin)["field"])'
3
ответ дан Adam Kurkiewicz 18 August 2018 в 08:22
поделиться
  • 1
    Вопрос не в поиске решения Python. См. Комментарии. – Andrew Barber 4 December 2014 в 20:38

Если в системе доступно [f 3], то:

$ pip install json-query

Примеры использования:

$ curl -s http://0/file.json | json-query
{
    "key":"value"    
}

$ curl -s http://0/file.json | json-query my.key
value

$ curl -s http://0/file.json | json-query my.keys.
key_1
key_2
key_3

$ curl -s http://0/file.json | json-query my.keys.2
value_2
2
ответ дан Alexey Dubkov 18 August 2018 в 08:22
поделиться
  • 1
    Как найти пакет json-query для использования длины json-массива? – Pruthvi Chitrala 25 August 2017 в 18:39

Кто-то, у кого также есть xml-файлы, может захотеть посмотреть на мой Xidel . Это беспроигрышный процессор JSONiq . (т. е. он также поддерживает XQuery для обработки xml или json)

Пример в вопросе:

 xidel -e 'json("http://twitter.com/users/username.json")("name")'

Или с моим собственным, нестандартным синтаксисом расширения:

 xidel -e 'json("http://twitter.com/users/username.json").name'
4
ответ дан BeniBela 18 August 2018 в 08:22
поделиться
  • 1
    Этот инструмент является soooooooooooo гораздо больше, чем просто парсер JSON ... – Roger 27 January 2017 в 10:45

TickTick является парсером JSON, написанным в bash (& lt; 250 строк кода)

Вот фрагмент автора из его статьи, Представьте мир, в котором поддерживает Bash JSON :

#!/bin/bash
. ticktick.sh

``  
  people = { 
    "Writers": [
      "Rod Serling",
      "Charles Beaumont",
      "Richard Matheson"
    ],  
    "Cast": {
      "Rod Serling": { "Episodes": 156 },
      "Martin Landau": { "Episodes": 2 },
      "William Shatner": { "Episodes": 2 } 
    }   
  }   
``  

function printDirectors() {
  echo "  The ``people.Directors.length()`` Directors are:"

  for director in ``people.Directors.items()``; do
    printf "    - %s\n" ${!director}
  done
}   

`` people.Directors = [ "John Brahm", "Douglas Heyes" ] ``
printDirectors

newDirector="Lamont Johnson"
`` people.Directors.push($newDirector) ``
printDirectors

echo "Shifted: "``people.Directors.shift()``
printDirectors

echo "Popped: "``people.Directors.pop()``
printDirectors
17
ответ дан Community 18 August 2018 в 08:22
поделиться

К сожалению, главный проголосовавший ответ, который использует grep, возвращает полное совпадение, которое не работает в моем сценарии, но если вы знаете, что формат JSON останется постоянным, вы можете использовать lookbehind и lookahead , чтобы извлечь только нужные значения.

# echo '{"TotalPages":33,"FooBar":"he\"llo","anotherValue":100}' | grep -Po '(?<="FooBar":")(.*?)(?=",)'
he\"llo
# echo '{"TotalPages":33,"FooBar":"he\"llo","anotherValue":100}' | grep -Po '(?<="TotalPages":)(.*?)(?=,)'
33
#  echo '{"TotalPages":33,"FooBar":"he\"llo","anotherValue":100}' | grep -Po '(?<="anotherValue":)(.*?)(?=})'
100
5
ответ дан Daniel Sokolowski 18 August 2018 в 08:22
поделиться
  • 1
    Фактически вы never знаете порядок элементов в словаре JSON. Они, по определению, неупорядочены. Это как раз и одна из основных причин, почему сканирование собственного анализатора JSON является обреченным подходом. – tripleee 18 June 2018 в 12:54

Вы спросили, как стрелять в ногу, и я здесь, чтобы предоставить боеприпасы:

curl -s 'http://twitter.com/users/username.json' | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^text/ {print $2}'

Вместо sed вы можете использовать tr -d '{}'. Но оставляя их полностью, кажется, тоже имеет желаемый эффект.

Если вы хотите удалить внешние кавычки, проведите результат выше через sed 's/\(^"\|"$\)//g'

Я думаю другие озвучивали достаточную тревогу. Я буду стоять рядом с мобильным телефоном, чтобы вызвать скорую. Пожар при готовности.

42
ответ дан Dennis Williamson 18 August 2018 в 08:22
поделиться
  • 1
    Таким образом, безумие гласит: stackoverflow.com/questions/1732348/… – Dennis Williamson 24 December 2009 в 01:12
  • 2
    Я прочитал все ответы, и это отлично работает для меня без каких-либо дополнительных зависимостей. +1 – eth0 26 January 2015 в 23:39
  • 3
    Это то, что я искал. Единственная коррекция - предоставленная команда sed для удаления кавычек не сработала для меня, я использовал sed 's / & quot; // g' вместо – AlexG 12 August 2015 в 12:43

Я использовал это для извлечения длительности видео с выхода ffprobe json:

MOVIE_INFO=`ffprobe "path/to/movie.mp4"  -show_streams -show_format -print_format json -v quiet` 
MOVIE_SECONDS=`echo "$MOVIE_INFO"|grep -w \"duration\" |tail -1 | cut -d\" -f4 |cut -d \. -f 1`

его можно использовать для извлечения значения из любого json:

value=`echo "$jsondata"|grep -w \"key_name\" |tail -1 | cut -d\" -f4
2
ответ дан Ehsan Chavoshi 18 August 2018 в 08:22
поделиться
  • 1
    Если предполагается, что это допустимый сценарий оболочки, пробелы вокруг знака равенства в последнем фрагменте являются синтаксической ошибкой. – tripleee 18 June 2018 в 12:55
  • 2
    @tripleee Исправлено. Tnx. – Ehsan Chavoshi 19 June 2018 в 13:22

Используйте поддержку JSON Python вместо использования awk!

Что-то вроде этого:

curl -s http://twitter.com/users/username.json | \
    python -c "import json,sys;obj=json.load(sys.stdin);print obj['name'];"
86
ответ дан Eliran Malka 18 August 2018 в 08:22
поделиться
  • 1
    Простите меня за то, что я придумал хороший ответ ...: Я постараюсь усерднее. Partisanship требует больше, чем писать awk-скрипт, чтобы избавиться от этого! – martinr 23 December 2009 в 23:45
  • 2
    Почему вы используете переменную obj в этом решении oneliner ?. Это бесполезно и вообще не хранится? Вы пишете меньше, используя json.load(sys.stdin)['"key']" в качестве примера, например: curl -sL httpbin.org/ip | python -c "import json,sys; print json.load(sys.stdin)['origin']". – erm3nda 15 February 2016 в 08:23

здесь вы можете сделать это с помощью awk

curl -sL 'http://twitter.com/users/username.json' | awk -F"," -v k="text" '{
    gsub(/{|}/,"")
    for(i=1;i<=NF;i++){
        if ( $i ~ k ){
            print $i
        }
    }
}'
4
ответ дан ghostdog74 18 August 2018 в 08:22
поделиться

Если кто-то просто хочет извлечь значения из простых объектов JSON без необходимости вложенных структур, можно использовать регулярные выражения, даже не выходя из bash.

Вот функция, которую я определил с помощью bash regular выражения, основанные на стандарте JSON :

function json_extract() {
  local key=$1
  local json=$2

  local string_regex='"([^"\]|\\.)*"'
  local number_regex='-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?'
  local value_regex="${string_regex}|${number_regex}|true|false|null"
  local pair_regex="\"${key}\"[[:space:]]*:[[:space:]]*(${value_regex})"

  if [[ ${json} =~ ${pair_regex} ]]; then
    echo $(sed 's/^"\|"$//g' <<< "${BASH_REMATCH[1]}")
  else
    return 1
  fi
}

Предостережения: объекты и массивы не поддерживаются как значение, но поддерживаются все другие типы значений, определенные в стандарте. Кроме того, пара будет сопоставляться независимо от того, насколько глубоко в документе JSON она сохраняется до тех пор, пока она имеет точно такое же имя ключа.

Используя пример OP:

$ json_extract text "$(curl 'http://twitter.com/users/username.json')"
My status

$ json_extract friends_count "$(curl 'http://twitter.com/users/username.json')"
245
3
ответ дан Helder Pereira 18 August 2018 в 08:22
поделиться

Niet - это инструмент, который поможет вам извлечь данные из json или yaml-файла непосредственно в ваш CLI оболочки / bash.

$ pip install niet

Рассмотрим json-файл с именем project. json со следующим содержимым:

{
  project: {
    meta: {
      name: project-sample
    }
}

Вы можете использовать niet следующим образом:

$ PROJECT_NAME=$(niet project.json project.meta.name)
$ echo ${PROJECT_NAME}
project-sample
2
ответ дан Herve 18 August 2018 в 08:22
поделиться

Вы можете попробовать что-то вроде этого -

curl -s 'http://twitter.com/users/jaypalsingh.json' | 
awk -F=":" -v RS="," '$1~/"text"/ {print}'
3
ответ дан jaypal singh 18 August 2018 в 08:22
поделиться

Чтобы быстро извлечь значения для определенного ключа, мне лично нравится использовать «grep -o», который возвращает только соответствие регулярному выражению. Например, чтобы получить поле «текст» из твитов, например:

grep -Po '"text":.*?[^\\]",' tweets.json

Это регулярное выражение более надежное, чем вы думаете; например, он отлично разбирается со строками, имеющими встроенные запятые и скрытыми кавычками внутри них. Я думаю, что с немного дополнительной работой вы могли бы создать тот, который на самом деле гарантированно извлекает значение, если он является атомарным. (Если у него есть вложение, то регулярное выражение не может этого сделать, конечно.)

И для дальнейшей очистки (хотя и сохранения исходного экранирования строки) вы можете использовать что-то вроде: | perl -pe 's/"text"://; s/^"//; s/",$//'. (Я сделал это для этого анализа .)

Для всех ненавистников, которые настаивают, что вы должны использовать настоящий парсер JSON - да, это важно для правильности, но

  1. Чтобы сделать действительно быстрый анализ, например, подсчитать значения, чтобы проверять ошибки очистки данных или получить общее представление о данных, быстрее удалять что-то из командной строки. Открытие редактора для написания скрипта отвлекает.
  2. grep -o на порядок быстрее, чем стандартная библиотека json Python, по крайней мере, когда это делается для твитов (которые составляют ~ 2 КБ каждый). Я не уверен, что это происходит только потому, что json медленный (я должен иногда сравнивать с yajl); но в принципе, регулярное выражение должно быть быстрее, поскольку оно является конечным состоянием и гораздо более оптимизированным, а не парсером, который должен поддерживать рекурсию, и в этом случае тратит много деревьев на сборку зданий для структур, которые вам не нужны. (Если кто-то написал конечный преобразователь состояния, который сделал правильный (ограниченный глубиной) JSON-анализ, это было бы фантастично! Тем временем у нас есть «grep -o».)

кода, я всегда использую настоящую парсинговую библиотеку. Я не пробовал jsawk , но если он работает хорошо, это касается точки № 1.

Последнее, более wackier, решение: я написал скрипт, который использует Python json и извлекает нужные вам ключи, в столбцы, разделенные вкладками; затем я прохожу через обертку вокруг awk, которая позволяет именованный доступ к столбцам. Здесь: скрипты json2tsv и tvvawk . Таким образом, для этого примера это будет:

json2tsv id text < tweets.json | tsvawk '{print "tweet " $id " is: " $text}'

Этот подход не относится к №2, более неэффективен, чем один скрипт Python, и он немного хрупкий: он принудительно нормализует новые строки и вкладки в строковые значения, чтобы играть хорошо с полем awk / разделенным на запись видом мира. Но это позволяет вам оставаться в командной строке с большей точностью, чем grep -o.

220
ответ дан Jens 18 August 2018 в 08:22
поделиться
  • 1
    Вы забыли о целых значениях. grep -Po '"text":(\d*?,|.*?[^\\]",)' – Robert 4 December 2013 в 03:52
  • 2
    Роберт: Верно, мое регулярное выражение было написано только для строковых значений для этого поля. Целые числа могут быть добавлены, как вы говорите. Если вы хотите все типы, вам нужно делать все больше и больше: booleans, null. А массивы и объекты требуют больше работы; возможна только ограниченная по глубине, под стандартными регулярными выражениями. – Brendan OConnor 5 December 2013 в 04:02
  • 3
    1. jq .name работает в командной строке и не требует «открытия редактора для написания сценария». 2. Неважно, насколько быстро ваше регулярное выражение может вывести результаты wrong – jfs 24 August 2014 в 21:50
  • 4
    и если вам нужны только значения, вы можете просто выбросить awk. | grep -Po '"text":.*?[^\\]",'|awk -F':' '{print $2}' – JeffCharter 6 September 2015 в 19:37
  • 5
    Похоже, что в OSX отсутствует опция -P. Я тестировал на OSX 10.11.5, а grep --version был grep (BSD grep) 2.5.1-FreeBSD. Я получил его, работая с расширенным регулярным выражением & quot; в OSX. Команда сверху будет grep -Eo '"text":.*?[^\\]",' tweets.json. – Jens 8 June 2016 в 13:14

Вы можете просто загрузить jq двоичный файл для вашей платформы и запустить (chmod +x jq):

$ curl 'https://twitter.com/users/username.json' | ./jq -r '.name'

Он извлекает атрибут "name" из объекта json.

jq homepage говорит, что это похоже на sed для данных JSON.

109
ответ дан jfs 18 August 2018 в 08:22
поделиться
  • 1
    Только для записи, jq - удивительный инструмент. – hoss 25 June 2013 в 17:48
  • 2
    Согласовано. Я не могу сравнивать с jsawk из принятого ответа, поскольку я этого не использовал, но для локальных экспериментов (где установка инструмента приемлема) я настоятельно рекомендую jq. Вот несколько более обширный пример, который берет каждый элемент массива и синтезирует новый объект JSON с выбранными данными: curl -s https://api.example.com/jobs | jq '.jobs[] | {id, o: .owner.username, dateCreated, s: .status.state}' – jbyler 21 April 2014 в 23:04
  • 3
    Люблю это. Очень легкий вес, и поскольку он находится в обычном старом C, его можно скомпилировать где угодно. – Benmj 21 October 2014 в 17:28
  • 4
    Самый практичный: для него не нужны сторонние библиотеки (в то время как jsawk) и прост в установке (OSX: brew install jq) – lauhub 19 December 2014 в 10:10
  • 5
    Это самый практичный и легко реализованный ответ для моего прецедента. Для системы Ubuntu (14.04) простая утилита apt-get install jq добавила инструмент в мою систему. Я собираю вывод JSON из ответов AWS CLI в jq, и он отлично работает, чтобы извлекать значения для определенных ключей, вложенных в ответ. – Brandon K 27 May 2015 в 15:01

Использование Bash с Python

Создайте функцию bash в вашем файле .bash_rc

function getJsonVal () { 
    python -c "import json,sys;sys.stdout.write(json.dumps(json.load(sys.stdin)$1))"; 
}

Затем

$ curl 'http://twitter.com/users/username.json' | getJsonVal "['text']"
My status
$ 

Вот такая же функция, но с проверкой ошибок.

function getJsonVal() {
   if [ \( $# -ne 1 \) -o \( -t 0 \) ]; then
       cat <<EOF
Usage: getJsonVal 'key' < /tmp/
 -- or -- 
 cat /tmp/input | getJsonVal 'key'
EOF
       return;
   fi;
   python -c "import json,sys;sys.stdout.write(json.dumps(json.load(sys.stdin)$1))";
}

Где $ # -ne 1 обеспечивает как минимум 1 вход, а -t 0 убедитесь, что вы перенаправляетесь из канала.

Приятное вещь об этой реализации заключается в том, что вы можете получить доступ к вложенным значениям json и получить json взамен! =)

Пример:

$ echo '{"foo": {"bar": "baz", "a": [1,2,3]}}' |  getJsonVal "['foo']['a'][1]"
2

Если вы хотите быть действительно фантастическим, вы могли бы довольно распечатать данные:

function getJsonVal () { 
    python -c "import json,sys;sys.stdout.write(json.dumps(json.load(sys.stdin)$1, sort_keys=True, indent=4))"; 
}

$ echo '{"foo": {"bar": "baz", "a": [1,2,3]}}' |  getJsonVal "['foo']"
{
    "a": [
        1, 
        2, 
        3
    ], 
    "bar": "baz"
}
36
ответ дан Joe Heyming 18 August 2018 в 08:22
поделиться
  • 1
    +1, но вы действительно должны избавиться от бесполезного использования [g1] cat – tripleee 19 February 2014 в 07:17
  • 2
    Однострочный без функции bash: curl http://foo | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["environment"][0]["name"]' – Cheeso 4 June 2014 в 01:53
  • 3
    sys.stdout.write(), если вы хотите, чтобы он работал как с python 2, так и с 3. – Per Johansson 27 June 2014 в 10:17
  • 4
    Я думаю, что он должен измениться на system.stdout.write (obj $ 1). Таким образом, вы можете сказать: getJsonVal & quot; ['environment'] ['name'] & quot ;, например, пример @Cheeso – Joe Heyming 7 July 2014 в 21:14
  • 5
    @Narek В этом случае он будет выглядеть так: function getJsonVal() { py -x "json.dumps(json.loads(x)$1, sort_keys=True, indent=4)"; } – Joe Heyming 22 September 2016 в 22:57

Вы можете использовать jshon :

curl 'http://twitter.com/users/username.json' | jshon -e text
5
ответ дан kev 18 August 2018 в 08:22
поделиться
  • 1
    На сайте говорится: «В два раза быстрее, 1/6-я память» ... и затем: «Jshon анализирует, читает и создает JSON. Он предназначен для максимально возможного использования внутри оболочки и заменяет хрупкие adhoc parsers, созданные из grep / sed / awk, а также супертяжелые однострочные парсеры из perl / python. & Quot; – Roger 27 January 2017 в 10:20
  • 2
    это указано как рекомендуемое решение для разбора JSON в Bash – qodeninja 8 July 2017 в 04:33

Версия Native Bash: также хорошо работает с обратными косыми чертами (\) и кавычками (")

function parse_json()
{
    echo $1 | \
    sed -e 's/[{}]/''/g' | \
    sed -e 's/", "/'\",\"'/g' | \
    sed -e 's/" ,"/'\",\"'/g' | \
    sed -e 's/" , "/'\",\"'/g' | \
    sed -e 's/","/'\"---SEPERATOR---\"'/g' | \
    awk -F=':' -v RS='---SEPERATOR---' "\$1~/\"$2\"/ {print}" | \
    sed -e "s/\"$2\"://" | \
    tr -d "\n\t" | \
    sed -e 's/\\"/"/g' | \
    sed -e 's/\\\\/\\/g' | \
    sed -e 's/^[ \t]*//g' | \
    sed -e 's/^"//'  -e 's/"$//'
}


parse_json '{"username":"john, doe","email":"john@doe.com"}' username
parse_json '{"username":"john doe","email":"john@doe.com"}' email

--- outputs ---

john, doe
johh@doe.com
17
ответ дан maikel 18 August 2018 в 08:22
поделиться
  • 1
    Это круто. Но если строка JSON содержит более одного ключа электронной почты, синтаксический анализатор выведет john@doe.com" & quot; john@doe.com – rtc11 6 April 2016 в 12:03

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

Например, рассмотрите инструмент jsonlookup , чтобы, если я скажу jsonlookup access token id он вернет атрибут id , определенный в атрибуте токен , определенный в атрибуте access из stdin, который, по-видимому, является данными JSON. Если атрибут не существует, инструмент ничего не возвращает (статус выхода 1). Если синтаксический анализ не выполняется, выйдите из состояния 2 и передайте сообщение stderr. Если поиск завершен, инструмент печатает значение атрибута.

Создав инструмент unix для точной цели извлечения значений JSON, вы можете легко использовать его в сценариях оболочки:

access_token=$(curl <some horrible crap> | jsonlookup access token id)

Любой язык будет использоваться для реализации jsonlookup . Вот довольно краткая версия python:

#!/usr/bin/python                                                               

import sys
import json

try: rep = json.loads(sys.stdin.read())
except:
    sys.stderr.write(sys.argv[0] + ": unable to parse JSON from stdin\n")
    sys.exit(2)
for key in sys.argv[1:]:
    if key not in rep:
        sys.exit(1)
    rep = rep[key]
print rep
3
ответ дан mcnabicus 18 August 2018 в 08:22
поделиться

Следуя указаниям MartinR и Boecko:

$ curl -s 'http://twitter.com/users/username.json' | python -mjson.tool

Это даст вам очень дружелюбный результат. Очень удобно:

$ curl -s 'http://twitter.com/users/username.json' | python -mjson.tool | grep my_key
116
ответ дан meetar 18 August 2018 в 08:22
поделиться
  • 1
    Как бы вы извлекли конкретный ключ, как спрашивает OP? – juan 28 March 2013 в 15:58
  • 2
    Лучший ответ пока imho, не нужно устанавливать что-либо еще на большинстве дистрибутивов, и вы можете | grep field. Благодаря! – Andrea Richiardi 12 May 2013 в 05:31
  • 3
    Все это делает формат JSON, если я не ошибаюсь. Он не позволяет вызывающему абоненту выбрать конкретное поле из вывода, равно как и решение xpath, или что-то, основанное на «JSON Pointer». – Cheeso 4 June 2014 в 01:42
  • 4
    или вы можете использовать pythonpy: curl 'http://twitter.com/users/username.json' | py --json_input -x 'x.name' – RussellStewart 14 September 2014 в 21:14
  • 5
    Я просто получаю пару ключевых значений, но не значение само по себе. – christopher 28 December 2017 в 11:15

Вот хорошая ссылка . В этом случае:

curl 'http://twitter.com/users/username.json' | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) { where = match(a[i], /\"text\"/); if(where) {print a[i]} }  }'
2
ответ дан Nathan Tuggy 18 August 2018 в 08:22
поделиться

Разбор JSON с PHP CLI

Возможно, вне темы, но поскольку приоритет царит, этот вопрос остается неполным без упоминания нашего надежного и верного PHP, я прав?

Используя тот же пример JSON, но давайте присваиваем его переменной для уменьшения неопределенности.

$ export JSON='{"hostname":"test","domainname":"example.com"}'

Теперь для корректности PHP, используя file_get_contents и php: // stdin обтекатель потоков.

$ echo $JSON|php -r 'echo json_decode(file_get_contents("php://stdin"))->hostname;'

или как указано с помощью fgets и уже открытого потока при константе CLI STDIN .

$ echo $JSON|php -r 'echo json_decode(fgets(STDIN))->hostname;'

NJoy!

19
ответ дан nickl- 18 August 2018 в 08:22
поделиться
  • 1
    Я использую то же самое, что работает также с fgets(STDIN) – Elvis Ciotti 2 April 2013 в 15:01
  • 2
    Вы даже можете использовать $argn вместо fgets(STDIN) – IcanDivideBy0 23 September 2013 в 12:50
  • 3
    К сожалению, $argn работает с флагом -E или -R, и только если содержимое JSON находится в одной строке ... – IcanDivideBy0 23 September 2013 в 12:58

Это хороший прецедент для pythonpy :

curl 'http://twitter.com/users/username.json' | py 'json.load(sys.stdin)["name"]'
3
ответ дан RussellStewart 18 August 2018 в 08:22
поделиться
  • 1
    Даже более короткий, python -c модуль здесь :) приятно. – erm3nda 15 February 2016 в 08:25

Для более сложного разбора JSON я предлагаю использовать python jsonpath module (by Stefan Goessner) -

  1. Установить его -

sudo easy_install -U jsonpath

  1. Использовать его -

Пример file.json (из http://goessner.net/articles/JsonPath ) -

{ "store": {
    "book": [ 
      { "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      { "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      { "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      { "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}

Разберите его (извлеките все названия книг с ценой & lt; 10) -

$ cat file.json | python -c "import sys, json, jsonpath; print '\n'.join(jsonpath.jsonpath(json.load(sys.stdin), 'store.book[?(@.price < 10)].title'))"

Выведет -

Sayings of the Century
Moby Dick

ПРИМЕЧАНИЕ. командная строка не включает проверку ошибок. для полного решения с проверкой ошибок вы должны создать небольшой скрипт python и обернуть код с помощью try-except.

4
ответ дан shlomosh 18 August 2018 в 08:22
поделиться
  • 1
    красивый идиома. Я даже не знаю Python, но это похоже на мощное решение – Sridhar-Sarnobat 20 August 2016 в 05:15
  • 2
    У меня возникла небольшая проблема с установкой jsonpath, поэтому была установлена ​​jsonpath_rw, поэтому вот что-то похожее вы можете попробовать, если выше не работает: 1) /usr/bin/python -m pip install jsonpath-rw 2) cat ~/trash/file.json | /usr/bin/python -c "from jsonpath_rw import jsonpath, parse; import sys,json; jsonpath_expr = parse('store.book[0]'); out = [match.value for match in jsonpath_expr.find(json.load(sys.stdin))]; print out;" (я использовал полный путь к двоичный код python, потому что у меня возникли проблемы с несколькими установленными питонами). – Sridhar-Sarnobat 20 August 2016 в 05:27

Версия, которая использует Ruby и http://flori.github.com/json/

$ < file.json ruby -e "require 'rubygems'; require 'json'; puts JSON.pretty_generate(JSON[STDIN.read]);"

или более кратко:

$ < file.json ruby -r rubygems -r json -e "puts JSON.pretty_generate(JSON[STDIN.read]);"
11
ответ дан slm 18 August 2018 в 08:22
поделиться
  • 1
    это мой любимый;) Кстати, вы можете сократить его с ruby ​​-rjson, чтобы потребовать библиотеку – lucapette 4 May 2011 в 11:57
  • 2
    Обратите внимание, что окончательный ; не требуется в Ruby (он используется только для конкатенации операторов, которые обычно находятся на отдельных строках в одну строку). – Zack Morris 15 August 2018 в 20:50

Это еще один bash & amp; python гибридный ответ. Я опубликовал этот ответ, потому что хотел обработать более сложный вывод JSON, но, уменьшив сложность моего приложения bash. Я хочу открыть следующий объект JSON из http://www.arcgis.com/sharing/rest/info?f=json в bash:

{
  "owningSystemUrl": "http://www.arcgis.com",
  "authInfo": {
    "tokenServicesUrl": "https://www.arcgis.com/sharing/rest/generateToken",
    "isTokenBasedSecurity": true
  }
}

Несмотря на то, что этот подход увеличивает сложность функции Python, использование bash упрощается:

function jsonGet {
  python -c 'import json,sys
o=json.load(sys.stdin)
k="'$1'"
if k != "":
  for a in k.split("."):
    if isinstance(o, dict):
      o=o[a] if a in o else ""
    elif isinstance(o, list):
      if a == "length":
        o=str(len(o))
      elif a == "join":
        o=",".join(o)
      else:
        o=o[int(a)]
    else:
      o=""
if isinstance(o, str) or isinstance(o, unicode):
  print o
else:
  print json.dumps(o)
'
}

curl -s http://www.arcgis.com/sharing/rest/info?f=json | jsonGet
curl -s http://www.arcgis.com/sharing/rest/info?f=json | jsonGet authInfo
curl -s http://www.arcgis.com/sharing/rest/info?f=json | jsonGet authInfo.tokenServicesUrl

Вывод вышеупомянутого скрипта:

Я добавил поддержку массивов, поэтому вы можете использовать .length, и если источник представляет собой строковый массив, вы можете использовать .join:

curl -s http://www.arcgis.com/sharing/rest/portals/self?f=pjson | jsonGet defaultBasemap.baseMapLayers.length
curl -s http://www.arcgis.com/sharing/rest/portals/self?f=pjson | jsonGet defaultBasemap.baseMapLayers.0.resourceInfo.tileInfo.lods
curl -s http://www.arcgis.com/sharing/rest/portals/self?f=pjson | jsonGet defaultBasemap.baseMapLayers.0.resourceInfo.tileInfo.lods.length
curl -s http://www.arcgis.com/sharing/rest/portals/self?f=pjson | jsonGet defaultBasemap.baseMapLayers.0.resourceInfo.tileInfo.lods.23

Какие выходы:

  • 1
  • [{"scale": 591657527.591555, "resolution": 156543.03392800014, "level": 0}, {"scale": 295828763.795777, "resolution": 78271.51696399994, "level": 1}, {"scale": 147914381.897889, "resolution": 39135.75848200009, "level": 2}, {"scale": 73957190.948944, "resolution": 19567.87924099992, "level": 3}, {"scale": 36978595.474472, "resolution" : «Уровень»: 4}, {«scale»: 18489297.737236, «resolution»: 4891.96981024998, «level»: 5}, {«scale»: 9244648.868618, «resolution»: 2445.98490512499, «level»: 6}, {"scale": 4622324.434309, "resolution": 1222.992452562495, "level": 7}, {"scale": 2311162.217155, "resolution": 611.4962262813797, "level": 8}, {"scale": 1155581.108577, "resolution" : 305.74811314055756, "level": 9}, {"scale": 577790.554289, "resolution": 152.87405657041106, "level": 10}, {"scale": 288895.277144, "resolution": 76.43702828507324, "level": 11}, {"scale": 144447.638572, "resolution": 38.21851414253662, "level": 12}, {"scale": 72223.819286, "resolution": 19.10925707126831, "level": 13}, {"scale": 36111.909643, "resolution" : 9.554628535634155, "level": 14}, {"scale": 18055.954822, "resolution": 4.77731426794937, "level ": 15}, {" scale ": 9027.977411," resolution ": 2.388657133974685," level ": 16}, {" scale ": 4513.988705," resolution ": 1.1943285668550503," level ": 17}, {" scale ": 2256.994353, «разрешение»: 0,5971642835598172, «уровень»: 18}, {«шкала»: 1128,497176, «разрешение»: 0,29858214164761665, «уровень»: 19}, {«шкала»: 564,248588, «разрешение»: 0.14929107082380833, уровень ": 20}, {" scale ": 282.124294," resolution ": 0.07464553541190416," level ": 21}, {" scale ": 141.062147," resolution ": 0.03732276770595208," level ": 22}, {" scale ": 70.5310735, «разрешение»: 0,01866138385297604, «уровень»: 23}]
  • 24
  • {"scale": 70.5310735, "resolution": 0.01866138385297604, "level": 23}
3
ответ дан Stephen Quan 18 August 2018 в 08:22
поделиться

На основании того, что некоторые из рекомендаций здесь (esp в комментариях) предложили использовать Python, я был разочарован, чтобы не найти пример.

Итак, вот один лайнер, чтобы получить один значение из некоторых данных JSON. Предполагается, что вы передаете данные в (откуда-то) и поэтому должны быть полезны в контексте сценариев.

echo '{"hostname":"test","domainname":"example.com"}' | python -c 'import json,sys;obj=json.load(sys.stdin);print obj[0]["hostname"]'
146
ответ дан Thiago Negri 18 August 2018 в 08:22
поделиться
  • 1
    Я добавил этот ответ ниже, чтобы использовать функцию bash: curl 'some_api' | getJsonVal 'key' – Joe Heyming 11 April 2014 в 23:06
  • 2
    pythonpy ( github.com/russell91/pythonpy почти всегда является лучшей альтернативой python -c, хотя он должен быть установлен с помощью pip. просто подключите json к py --ji -x 'x[0]["hostname"]'. не хотели использовать встроенную поддержку json_input, вы все равно можете автоматически импортировать этот импорт как py 'json.loads(sys.stdin)[0]["hostname"]' – RussellStewart 14 September 2014 в 21:18
  • 3
    Благодаря! Для более быстрого анализа и анализа JSON я включил его в функцию bash: jsonq() { python -c "import sys,json; obj=json.load(sys.stdin); print($1)"; }, чтобы я мог написать: curl ...... | jsonq 'json.dumps([key["token"] for key in obj], indent=2)' & amp; больше подобных страшных вещей ... Btw, obj[0] кажется ненужным, похоже, что только obj работает нормально в случаях по умолчанию (?). – akavel 23 March 2015 в 14:05
  • 4
    Благодарю. Я сделал это в отношении JSON немного лучше, чем печать: jsonq() { python -c "import sys,json; obj=json.load(sys.stdin); sys.stdout.write(json.dumps($1))"; } – Adam K Dean 1 March 2016 в 18:58
  • 5
    obj[0] вызывает ошибку при разборе { "port":5555 }. Прекрасно работает после удаления [0]. – CyberEd 16 August 2016 в 20:49

Теперь, когда Powershell - это кросс-платформа, я подумал, что я брошу туда, потому что считаю это довольно интуитивным и чрезвычайно простым.

curl -s 'https://api.github.com/users/lambda' | ConvertFrom-Json 

ConvertFrom-Json преобразует JSON в пользовательский объект Powershell, поэтому вы можете легко работать со свойствами с этой точки вперед. Если вы хотели бы только свойство id, вы бы просто сделали это:

curl -s 'https://api.github.com/users/lambda' | ConvertFrom-Json | select -ExpandProperty id

Если вы хотите вызвать все это из Bash, тогда вам придется называть его как это:

powershell 'curl -s "https://api.github.com/users/lambda" | ConvertFrom-Json'

Конечно, есть чистый способ Powershell сделать это без завитки, что было бы:

Invoke-WebRequest 'https://api.github.com/users/lambda' | select -ExpandProperty Content | ConvertFrom-Json

Наконец, есть также «ConvertTo-Json», который преобразует пользовательский объект для JSON так же легко. Вот пример:

(New-Object PsObject -Property @{ Name = "Tester"; SomeList = @('one','two','three')}) | ConvertTo-Json

Что создавало бы хороший JSON вот так:

{
"Name":  "Tester",
"SomeList":  [
                 "one",
                 "two",
                 "three"
             ]

}

По общему признанию, использование оболочки Windows в Unix несколько кощунственный, но Powershell действительно хорош в некоторых вещах, и парсинг JSON и XML - это пара из них. Это страница GitHub для кросс-платформенной версии https://github.com/PowerShell/PowerShell

4
ответ дан user2233949 18 August 2018 в 08:22
поделиться
  • 1
    несмотря на то, что вы продвигаете новую стратегию Microsoft с открытым исходным кодом своих инструментов и включаете иностранные инструменты с открытым исходным кодом. Это хорошо для нашего мира. – Alex 22 June 2017 в 15:58

Если у вас есть php:

php -r 'var_export(json_decode(`curl http://twitter.com/users/username.json`, 1));'

Например: у нас есть ресурс, который предоставляет json странам iso-коды: http://country.io/iso3.json и мы можем легко увидеть его в оболочке с curl:

curl http://country.io/iso3.json

, но она выглядит не очень удобной и не читаемой, лучше разобрать json и увидеть читаемую структуру:

php -r 'var_export(json_decode(`curl http://country.io/iso3.json`, 1));'

Этот код напечатает что-то вроде:

array (
  'BD' => 'BGD',
  'BE' => 'BEL',
  'BF' => 'BFA',
  'BG' => 'BGR',
  'BA' => 'BIH',
  'BB' => 'BRB',
  'WF' => 'WLF',
  'BL' => 'BLM',
  ...

, если у вас есть вложенные массивы, этот вывод будет выглядеть намного лучше ...

Надеюсь, это поможет ...

4
ответ дан Vladimir Kovpak 18 August 2018 в 08:22
поделиться

Использование Node.js

Если система имеет , возможно использовать -p print и -e флаги сценария evaulate с JSON.parse , чтобы вытащить любое требуемое значение.

Простой пример с использованием строки JSON { "foo": "bar" } и вытаскивание значения «foo»:

$ node -pe 'JSON.parse(process.argv[1]).foo' '{ "foo": "bar" }'
bar

] Поскольку у нас есть доступ к cat и другим утилитам, мы можем использовать это для файлов:

$ node -pe 'JSON.parse(process.argv[1]).foo' "$(cat foobar.json)"
bar

Или любой другой формат, такой как URL-адрес, содержащий JSON:

$ node -pe 'JSON.parse(process.argv[1]).name' "$(curl -s https://api.github.com/users/trevorsenior)"
Trevor Senior
75
ответ дан x9hb8wcy6quezjk 18 August 2018 в 08:22
поделиться
  • 1
    благодаря! но в моем случае он работает только с флагом -e node -p -e 'JSON.parse(process.argv[1]).foo' '{ "foo": "bar" }' – Rnd_d 26 November 2013 в 01:02
  • 2
    Трубы! curl -s https://api.github.com/users/trevorsenior | node -pe "JSON.parse(require('fs').readFileSync('/dev/stdin').toString()).name" – nicerobot 7 May 2014 в 20:19
  • 3
    это мое любимое решение; используйте язык (javascript) для анализа структуры данных, которая является для него естественной (JSON). кажется наиболее правильным . также - узел, вероятно, уже доступен в системе, и вам не придется калечить двоичные файлы jq (который выглядит как другой правильный выбор). – Eliran Malka 1 March 2017 в 16:05
  • 4
    Это функция сценария bash: # jsonv получает значение json-объекта для определенного атрибута # первым параметром является json document # второй параметр - это атрибут, значение которого должно быть возвращено get_json_attribute_value () {node -pe 'JSON.parse (process. argv [1]) [process.argv [2]] '' $ 1 " & Quot; $ 2 & Quot; } – Youness 4 July 2017 в 23:35
  • 5
    – Ilya Boyandin 15 October 2018 в 10:21