Перейти к основному содержимому
Версия: 4.3.58

Извлечение данных из JSON документов

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

Содержание:

Формат выражения

Путь (выражение) - это последовательность ключей, разделённых точкой. Ключ может содержать специальные символы подстановки * и ?. Для доступа к значению массива используйте индекс в качестве ключа. Для получения количества элементов в массиве или для доступа к дочернему пути используйте символ #. Символы точка (.) и подстановка (*, ?) могут быть экранированы символом \.

Путь предназначен для простого представления в виде серии компонентов, разделенных символом .. Наряду с символом . есть еще несколько, которые имеют специальные значения, включая |, #, @, \, *, ! и ?

Пример

Исходный JSON

{
"name": {"first": "Tom", "last": "Anderson"},
"age":37,
"children": ["Sara","Alex","Jack"],
"fav.movie": "Deer Hunter",
"friends": [
{"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
{"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
{"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
]
}

Общая информация

В большинстве случаев необходимо получить значения по имени объекта или индексу массива.

name.last              "Anderson"
name.first "Tom"
age 37
children ["Sara","Alex","Jack"]
children.0 "Sara"
children.1 "Alex"
friends.1 {"first": "Roger", "last": "Craig", "age": 68}
friends.1.first "Roger"

Использование wildcard маски

В ключе могут содержаться специальные символы подстановки * и ?, где * соответствует любому набору из нуля и более символов, а ? — любому одному символу.

child*.2               "Jack"
c?ildren.0 "Sara"

Символы экранирования

Условные обозначения, такие как ., * и ? можно экранировать с помощью \.

fav\.movie             "Deer Hunter"

Для корректного экранирования символа \ при жестком кодировании пути в исходном коде, также необходимо убедиться, что он правильно экранирован.

val := gjson.Get(json, "fav\\.movie")  // необходимо экранировать `\`
val := gjson.Get(json, `fav\.movie`) // нет необходимости экранировать `\`
let val = gjson::get(json, "fav\\.movie")      // необходимо экранировать `\`
let val = gjson::get(json, r#"fav\.movie"#) // нет необходимости экранировать `\`

Массивы

Символ # позволяет ра в массивах JSON.

Чтобы получить длину массива, Вы просто будете использовать # сам по себе.

Символ # позволяет работать с JSON массивами.

Чтобы получить длину массива, вам просто нужно использовать символ # сам по себе.

friends.#              3
friends.#.age [44,68,47]

Запросы

Вы также можете запросить массив для первого совпадения, используя #(...), или найти все совпадения с помощью #(...)#. Запросы поддерживают операторы сравнения ==, !=, <, <=, >, >=, а также операторы простого соответствия % (как) и !% (не как).

friends.#(last=="Murphy").first     "Dale"
friends.#(last=="Murphy")#.first ["Dale","Jane"]
friends.#(age>45)#.last ["Craig","Murphy"]
friends.#(first%"D*").last "Murphy"
friends.#(first!%"D*").last "Craig"

Чтобы запросить значение не объекта в массиве, можно пропустить строку справа от оператора.

children.#(!%"**a**")                 "Alex"
children.#(%"**a**")# ["Sara","Jack"]

Вложенные запросы разрешены.

friends.#(nets.#(=="fb"))#.first  >> ["Dale","Roger"]

Операторы тильда (~) преобразуют значение к булеву типу перед сравнением. Поддерживаемые типы сравнений тильдой:

  • ~true: преобразует значения, похожие на true, к true;
  • ~false: преобразует ложные и не существующие значения к true
  • null: преобразует null и не существующие значения к true.
  • * (звездочка): преобразует любое существующее значение к true.

Например, используя следующий JSON:

{
"vals": [
{ "a": 1, "b": true },
{ "a": 2, "b": true },
{ "a": 3, "b": false },
{ "a": 4, "b": "0" },
{ "a": 5, "b": 0 },
{ "a": 6, "b": "1" },
{ "a": 7, "b": 1 },
{ "a": 8, "b": "true" },
{ "a": 9, "b": false },
{ "a": 10, "b": null },
{ "a": 11 }
]
}

Теперь Вы можете запросить все значения true(ish) или false(ish):

vals.#(b==~true)#.a    >> [1,2,6,7,8]
vals.#(b==~false)#.a >> [3,4,5,9,10,11]

«Последнее значение, которого не было, считается ложным.

Проверка на существование нулевого значения и явного значения:

vals.((b==NULL)).a >> [10, 11]  
vals.(((b == NULL)) ).a >> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
vals.(!((b != NULL)).b).a >> 11»

Точка vs Pipe

Точка (.) — это стандартный разделитель, но можно использовать и символ pipe (|). В большинстве случаев они дают одинаковые результаты. Исключения — когда | используется после символа # для массивов и запросов. В тех случаях, когда | отличается от ., это происходит, когда оно используется после для массивов и запросов.

Вот несколько примеров:

friends.0.first                     "Dale"
friends|0.first "Dale"
friends.0|first "Dale"
friends|0|first "Dale"
friends|# 3
friends.# 3
friends.#(last="Murphy")# [{"first": "Dale", "last": "Murphy", "age": 44},{"first": "Jane", "last": "Murphy", "age": 47}]
friends.#(last="Murphy")#.first ["Dale","Jane"]
friends.#(last="Murphy")#|first <non-existent>
friends.#(last="Murphy")#.0 []
friends.#(last="Murphy")#|0 {"first": "Dale", "last": "Murphy", "age": 44}
friends.#(last="Murphy")#.# []
friends.#(last="Murphy")#|# 2

Давайте разберем некоторые из них.

Применение выражения friends.#(last="Murphy")# даёт следующий результат

[{"first": "Dale", "last": "Murphy", "age": 44},{"first": "Jane", "last": "Murphy", "age": 47}]

Суффикс .first будет обрабатывать путь first для каждого элемента массива before и вернёт результат:

["Dale","Jane"]

Но суффикс |first на самом деле обрабатывает first путь после предыдущего результата. Поскольку предыдущий результат представляет собой массив, а не объект, его невозможно обработать, поскольку first не существует.

Тем не менее суффикс |0 возвращает

{"first": "Dale", "last": "Murphy", "age": 44}

Потому что 0 - это первый индекс предыдущего результата.

Модификаторы

Модификатор — это компонент пути, который выполняет пользовательскую обработку JSON.

Например, применение встроенного модификатора @reverse в приведенном выше JSON вернёт инвертированный массив children:

children.@reverse                   ["Jack","Alex","Sara"]
children.@reverse.0 "Jack"

Существуют следующие встроенные модификаторы:

  • @reverse: - инвертировать массив или элементы объекта;
  • @ugly: - удаляет все пробелы из JSON;
  • @pretty: - делает JSON более удобочитаемым для человека;
  • @this: - возвращает текущий элемент; можно использовать для извлечения корневого элемента;
  • @valid: - проверяет что документ - валидный JSON;
  • @flatten: - преобразует массив в плоский список;
  • @join: - объединяет несколько объектов в один объект;
  • @keys: - возвращает массив ключей для объекта;
  • @values: - возвращает массив значений для объекта;
  • @tostr: - преобразует JSON в строку, обертывает строку JSON;
  • @fromstr: - преобразует строку из JSON, разворачивает строку JSON;
  • @group: - группирует массивы объектов (см. e4fc67c);
  • @dig: - позволяет искать значения в глубоких или произвольно вложенных документах JSON не указывая точный путь до элементов;

Модификаторы аргументов

Модификатор может принимать опциональный аргумент. Аргументом может быть действительный JSON объект или просто символы.

Например, модификатор @pretty принимает в качестве аргумента JSON объект:

@pretty:{"sortKeys":true}

Это делает JSON красивым и упорядочивает все его ключи.

{
"age":37,
"children": ["Sara","Alex","Jack"],
"fav.movie": "Deer Hunter",
"friends": [
{"age": 44, "first": "Dale", "last": "Murphy"},
{"age": 68, "first": "Roger", "last": "Craig"},
{"age": 47, "first": "Jane", "last": "Murphy"}
],
"name": {"first": "Tom", "last": "Anderson"}
}

Новый JSON как продукт нескольких выражений извлечения

Можно соединять несколько путей в один, чтобы сформировать новый документ.
Если разделить запятыми пути между [...] или {...}, получится новый массив или объект соответственно.

Например, используя заданный мультипуть:

{name.first,age,"the_murphys":friends.#(last="Murphy")#.first}

мы выбрали имя, возраст и имя для друзей с фамилией "Murphy".

Обратите внимание, что можно предоставить необязательный ключ, в данном случае the_murphys. Это позволит принудительно назначить ключ значению. В противном случае будет использоваться название фактического поля, в данном случае это first. Если имя определить невозможно, то используется _.

В результате получается:

{"first":"Tom","age":37,"the_murphys":["Dale","Jane"]}

Литералы

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

Литерал JSON начинается с символа объявления !.

Например, для выражения:

{name.first,age,"company":!"Happysoft","employed":!true}

выбрано имя и возраст, к ним добавлены два новых поля: company и employed.

Результат:

{"first":"Tom","age":37,"company":"Happysoft","employed":true}