std/json
SourceEditЭтот модуль реализует простой, высокопроизводительный парсер JSON. JSON (JavaScript Object Notation) — это лёгкий формат обмена данными, удобный для чтения и записи человеком (в отличие от XML). Он легко парсируется и генерируется машинами. JSON основан на подмножестве языка программирования JavaScript, Стандарт ECMA-262 3-го издания — декабрь 1999 года.
См. также
Обзор
Парсинг JSON
JSON часто поступает в вашу программу (через API или файл) в виде string. Первый шаг — преобразовать его из сериализованной формы в структуру вложенных объектов, называемую JsonNode.
Процедура parseJson принимает строку, содержащую JSON, и возвращает объект JsonNode. Это объект-вариант, и он может быть JObject, JArray, JString, JInt, JFloat, JBool или JNull. Вид этого объекта-варианта проверяется с помощью доступа kind.
Для JsonNode, чей вид JObject, вы можете получить доступ к его полям с помощью оператора [] . Следующий пример демонстрирует это:
import std/json
let jsonNode = parseJson("""{"key": 3.14}""")
doAssert jsonNode.kind == JObject
doAssert jsonNode["key"].kind == JFloat Чтение значений
После получения JsonNode, извлечение значений можно выполнить, используя одну из вспомогательных процедур, которые включают:
getIntgetFloatgetStrgetBool
Для получения значения "key" вы можете сделать следующее:
import std/json
let jsonNode = parseJson("""{"key": 3.14}""")
doAssert jsonNode["key"].getFloat() == 3.14 Важно: Оператор [] вызовет исключение, если указанное поле не существует.
Обработка необязательных ключей
Используя оператор {} вместо [], он вернёт nil при отсутствии поля. Семейство процедур get вернёт значение по умолчанию для типа при вызове на nil.
import std/json
let jsonNode = parseJson("{}")
doAssert jsonNode{"nope"}.getInt() == 0
doAssert jsonNode{"nope"}.getFloat() == 0
doAssert jsonNode{"nope"}.getStr() == ""
doAssert jsonNode{"nope"}.getBool() == false Использование значений по умолчанию
Вспомогательные функции семейства get также принимают дополнительный параметр, который позволяет использовать значение по умолчанию, если значение ключа null:
import std/json
let jsonNode = parseJson("""{"key": 3.14, "key2": null}""")
doAssert jsonNode["key"].getFloat(6.28) == 3.14
doAssert jsonNode["key2"].getFloat(3.14) == 3.14
doAssert jsonNode{"nope"}.getFloat(3.14) == 3.14 # note the {} Распаковка
Помимо чтения динамических данных, Nim также может распаковывать JSON напрямую в тип с помощью макроса to.
Примечание: Используйте Option для ключей, которые иногда отсутствуют в ответах JSON, и обрамляйте ключи с зарезервированным ключевым словом в обратные кавычки.
import std/json
import std/options
type
User = object
name: string
age: int
`type`: Option[string]
let userJson = parseJson("""{ "name": "Nim", "age": 12 }""")
let user = to(userJson, User)
if user.`type`.isSome():
assert user.`type`.get() != "robot" Создание JSON
Этот модуль также может использоваться для удобного создания JSON с помощью оператора %*:
import std/json
var hisName = "John"
let herAge = 31
var j = %*
[
{ "name": hisName, "age": 30 },
{ "name": "Susan", "age": herAge }
]
var j2 = %* {"name": "Isaac", "books": ["Robot Dreams"]}
j2["details"] = %* {"age":35, "pi":3.1415}
echo j2 См. также: std/jsonutils для привязываемой сериализации/десериализации JSON произвольных типов.
Пример:
import std/json
## Note: for JObject, key ordering is preserved, unlike in some languages,
## this is convenient for some use cases. Example:
type Foo = object
a1, a2, a0, a3, a4: int
doAssert $(%* Foo()) == """{"a1":0,"a2":0,"a0":0,"a3":0,"a4":0}""" Импорты
- hashes, tables, strutils, lexbase, streams, macros, parsejson, options, since
Типы
Процедуры
proc `$`(node: JsonNode): string {....raises: [], tags: [], forbids: [].}- Преобразует
nodeв его JSON представление на одной строке. Исходный код Редактировать proc `%`(b: bool): JsonNode {....raises: [], tags: [], forbids: [].}- Общий конструктор для JSON данных. Создаёт новый
JBool JsonNode. Исходный код Редактировать proc `%`(keyVals: openArray[tuple[key: string, val: JsonNode]]): JsonNode {. ...raises: [], tags: [], forbids: [].}- Общий конструктор для JSON данных. Создаёт новый
JObject JsonNode. Исходный код Редактировать proc `%`(n: BiggestInt): JsonNode {....raises: [], tags: [], forbids: [].}- Общий конструктор для JSON данных. Создаёт новый
JInt JsonNode. Исходный код Редактировать proc `%`(n: BiggestUInt): JsonNode {....raises: [], tags: [], forbids: [].}- Общий конструктор для JSON данных. Создаёт новый
JInt JsonNode. Исходный код Редактировать proc `%`(n: float): JsonNode {....raises: [], tags: [], forbids: [].}- Общий конструктор для JSON данных. Создаёт новый
JFloat JsonNode.Пример:
assert $(%[NaN, Inf, -Inf, 0.0, -0.0, 1.0, 1e-2]) == """["nan","inf","-inf",0.0,-0.0,1.0,0.01]""" assert (%NaN).kind == JString assert (%0.0).kind == JFloat
Исходный код Редактировать proc `%`(n: int): JsonNode {....raises: [], tags: [], forbids: [].}- Общий конструктор для JSON данных. Создаёт новый
JInt JsonNode. Исходный код Редактировать proc `%`(n: uint): JsonNode {....raises: [], tags: [], forbids: [].}- Общий конструктор для JSON данных. Создаёт новый
JInt JsonNode. Исходный код Редактировать proc `%`(o: enum): JsonNode
- Создаёт JsonNode, представляющий указанное значение перечисления в виде строки. Создаёт новый
JString JsonNode. Исходный код Редактировать proc `%`(o: ref object): JsonNode
- Общий конструктор для JSON данных. Создаёт новый
JObject JsonNodeИсходный код Редактировать proc `%`(s: string): JsonNode {....raises: [], tags: [], forbids: [].}- Общий конструктор для JSON данных. Создаёт новый
JString JsonNode. Исходный код Редактировать proc `%`[T: object](o: T): JsonNode
- Создаёт JsonNode из кортежей и объектов. Исходный код Редактировать
proc `%`[T](elements: openArray[T]): JsonNode
- Общий конструктор для JSON данных. Создаёт новый
JArray JsonNodeИсходный код Редактировать proc `%`[T](opt: Option[T]): JsonNode
- Общий конструктор для JSON данных. Создаёт новый
JNull JsonNode, еслиoptпусто, иначе делегирует подлежащему значению. Исходный код Редактировать proc `%`[T](table: Table[string, T] | OrderedTable[string, T]): JsonNode
- Общий конструктор для JSON данных. Создаёт новый
JObject JsonNode. Исходный код Редактировать proc `==`(a, b: JsonNode): bool {.noSideEffect, ...raises: [], tags: [RootEffect], forbids: [].}- Проверка двух узлов на равенство Исходный код Редактировать
proc `[]`(node: JsonNode; index: BackwardsIndex): JsonNode {.inline, ...raises: [], tags: [], forbids: [].}-
Получение узла по
array.len-iв массиве через оператор^.Например,
j[^i]— это сокращение дляj[j.len-i].Пример:
let j = parseJson("[1,2,3,4,5]") doAssert j[^1].getInt == 5 doAssert j[^2].getInt == 4Исходный код Редактировать proc `[]`(node: JsonNode; index: int): JsonNode {.inline, ...raises: [], tags: [], forbids: [].}- Получение узла по
indexв массиве. Результат неопределён, еслиindexвыходит за границы, но при включённых проверках границ массива он приведёт к исключению. Исходный код Редактировать proc `[]`(node: JsonNode; name: string): JsonNode {.inline, ...raises: [KeyError], tags: [], forbids: [].}- Получение поля из
JObject, которое не должно быть nil. Если значение поnameне существует, генерируется KeyError. Исходный код Редактировать proc `[]`[U, V](a: JsonNode; x: HSlice[U, V]): JsonNode
-
Операция среза для JArray.
Возвращает включительный диапазон
[a[x.a], a[x.b]]:Пример:
import std/json let arr = %[0,1,2,3,4,5] doAssert arr[2..4] == %[2,3,4] doAssert arr[2..^2] == %[2,3,4] doAssert arr[^4..^2] == %[2,3,4]
Исходный код Редактировать proc `[]=`(obj: JsonNode; key: string; val: JsonNode) {.inline, ...raises: [], tags: [], forbids: [].}- Установка поля в
JObject. Исходный код Редактировать proc add(father, child: JsonNode) {....raises: [], tags: [], forbids: [].}- Добавляет
childв узел JArrayfather. Исходный код Редактировать proc add(obj: JsonNode; key: string; val: JsonNode) {....raises: [], tags: [], forbids: [].}- Установка поля в
JObject. Исходный код Редактировать proc contains(node: JsonNode; key: string): bool {....raises: [], tags: [], forbids: [].}- Проверка, существует ли
keyвnode. Исходный код Редактировать proc contains(node: JsonNode; val: JsonNode): bool {....raises: [], tags: [RootEffect], forbids: [].}- Проверка, существует ли
valв массивеnode. Исходный код Редактировать proc copy(p: JsonNode): JsonNode {....raises: [], tags: [], forbids: [].}- Выполняет глубокую копию
p. Исходный код Редактировать proc delete(obj: JsonNode; key: string) {....raises: [KeyError], tags: [], forbids: [].}- Удаляет
obj[key]. Исходный код Редактировать proc escapeJson(s: string): string {....raises: [], tags: [], forbids: [].}- Преобразует строку
sв её JSON представление с кавычками. Исходный код Редактировать proc escapeJson(s: string; result: var string) {....raises: [], tags: [], forbids: [].}- Преобразует строку
sв её JSON представление с кавычками. Добавляет вresult. Исходный код Редактировать
proc escapeJsonUnquoted(s: string): string {....raises: [], tags: [], forbids: [].}- Преобразует строку
sв её JSON представление без кавычек. Исходный код Изменить proc escapeJsonUnquoted(s: string; result: var string) {....raises: [], tags: [], forbids: [].}- Преобразует строку
sв её JSON представление без кавычек. Добавляет кresult. Исходный код Изменить proc getBiggestInt(n: JsonNode; default: BiggestInt = 0): BiggestInt {. ...raises: [], tags: [], forbids: [].}-
Возвращает значение BiggestInt из
JInt JsonNode.Возвращает
Исходный код Изменитьdefaultеслиnне являетсяJInt, или еслиnравно null. proc getBool(n: JsonNode; default: bool = false): bool {....raises: [], tags: [], forbids: [].}-
Возвращает значение bool из
JBool JsonNode.Возвращает
Исходный код Изменитьdefaultеслиnне являетсяJBool, или еслиnравно null. proc getElems(n: JsonNode; default: seq[JsonNode] = @[]): seq[JsonNode] {. ...raises: [], tags: [], forbids: [].}-
Возвращает массив из
JArray JsonNode.Возвращает
Исходный код Изменитьdefaultеслиnне являетсяJArray, или еслиnравно null. proc getFields(n: JsonNode; default = initOrderedTable[string, JsonNode](2)): OrderedTable[ string, JsonNode] {....raises: [], tags: [], forbids: [].}-
Возвращает пары ключ-значение из
JObject JsonNode.Возвращает
Исходный код Изменитьdefaultеслиnне являетсяJObject, или еслиnравно null. proc getFloat(n: JsonNode; default: float = 0.0): float {....raises: [], tags: [], forbids: [].}-
Возвращает значение float из
JFloat JsonNode.Возвращает
Исходный код Изменитьdefaultеслиnне являетсяJFloatилиJInt, или еслиnравно null. proc getInt(n: JsonNode; default: int = 0): int {....raises: [], tags: [], forbids: [].}-
Возвращает значение int из
JInt JsonNode.Возвращает
Исходный код Изменитьdefaultеслиnне являетсяJInt, или еслиnравно null. proc getOrDefault(node: JsonNode; key: string): JsonNode {....raises: [], tags: [], forbids: [].}- Получает поле из
nodeЕслиnodeравно null или не является объектом, или поле поkeyне существует, возвращает null Исходный код Изменить proc getStr(n: JsonNode; default: string = ""): string {....raises: [], tags: [], forbids: [].}-
Возвращает строковое значение из
JString JsonNode.Возвращает
Исходный код Изменитьdefaultеслиnне являетсяJString, или еслиnравно null. proc hash(n: JsonNode): Hash {.noSideEffect, ...raises: [Exception], tags: [RootEffect], forbids: [].}- Вычисляет хеш для узла JSON Исходный код Изменить
proc hash(n: OrderedTable[string, JsonNode]): Hash {.noSideEffect, ...raises: [Exception], tags: [RootEffect], forbids: [].}- Исходный код Изменить
proc hasKey(node: JsonNode; key: string): bool {....raises: [], tags: [], forbids: [].}- Проверяет существование
keyвnodeИсходный код Изменить proc len(n: JsonNode): int {....raises: [], tags: [], forbids: [].}- Если
nявляется массивом, возвращает количество элементов. Еслиnявляется объектом, возвращает количество пар. Иначе возвращает 0. Исходный код Изменить proc newJArray(): JsonNode {....raises: [], tags: [], forbids: [].}- Создаёт новый массив
JArray JsonNodeИсходный код Изменить proc newJBool(b: bool): JsonNode {....raises: [], tags: [], forbids: [].}- Создаёт новый булевый
JBool JsonNode. Исходный код Изменить proc newJFloat(n: float): JsonNode {....raises: [], tags: [], forbids: [].}- Создаёт новый
JFloat JsonNode. Исходный код Изменить proc newJInt(n: BiggestInt): JsonNode {....raises: [], tags: [], forbids: [].}- Создаёт новый
JInt JsonNode. Исходный код Изменить proc newJNull(): JsonNode {....raises: [], tags: [], forbids: [].}- Создаёт новый
JNull JsonNode. Исходный код Изменить proc newJObject(): JsonNode {....raises: [], tags: [], forbids: [].}- Создаёт новый объект
JObject JsonNodeИсходный код Изменить proc newJString(s: string): JsonNode {....raises: [], tags: [], forbids: [].}- Создаёт новую строку
JString JsonNode. Исходный код Изменить proc parseFile(filename: string): JsonNode {. ...raises: [IOError, OSError, JsonParsingError, ValueError], tags: [ReadIOEffect, WriteIOEffect], forbids: [].}- Парсит
fileвJsonNode. Еслиfileсодержит дополнительные данные, будет выброшено исключениеJsonParsingError. Исходный код Изменить proc parseJson(buffer: string; rawIntegers = false; rawFloats = false): JsonNode {. ...raises: [IOError, OSError, JsonParsingError, ValueError], tags: [ReadIOEffect, WriteIOEffect], forbids: [].}- Парсит JSON из
buffer. Еслиbufferсодержит дополнительные данные, будет выброшено исключениеJsonParsingError. ЕслиrawIntegerstrue, целочисленные литералы не будут преобразовываться в полеJInt, а будут сохранены как исходные числа черезJString. ЕслиrawFloatstrue, литералы с плавающей точкой не будут преобразовываться в полеJFloat, а будут сохранены как исходные числа черезJString. Исходный код Изменить proc parseJson(s: Stream; filename: string = ""; rawIntegers = false; rawFloats = false): JsonNode {. ...raises: [IOError, OSError, IOError, OSError, JsonParsingError, ValueError], tags: [ReadIOEffect, WriteIOEffect], forbids: [].}- Парсит из потока
sвJsonNode.filenameнеобходимо только для красивых сообщений об ошибках. Еслиsсодержит дополнительные данные, будет выброшено исключениеJsonParsingError. Закрывает потокsпосле завершения. ЕслиrawIntegerstrue, целочисленные литералы не будут преобразовываться в полеJInt, а будут сохранены как исходные числа черезJString. ЕслиrawFloatstrue, литералы с плавающей точкой не будут преобразовываться в полеJFloat, а будут сохранены как исходные числа черезJString. Исходный код Изменить
proc pretty(node: JsonNode; indent = 2): string {....raises: [], tags: [], forbids: [].}-
Возвращает JSON-представление
node, с отступами и на нескольких строках.Аналогично prettyprint в Python.
Пример:
let j = %* {"name": "Isaac", "books": ["Robot Dreams"], "details": {"age": 35, "pi": 3.1415}} doAssert pretty(j) == """ { "name": "Isaac", "books": [ "Robot Dreams" ], "details": { "age": 35, "pi": 3.1415 } }"""Исходный код Изменить proc to[T](node: JsonNode; t: typedesc[T]): T
-
Распаковывает указанный узел в тип объекта.
Известные ограничения:
- Гетерогенные массивы не поддерживаются.
- Множества в вариантах объектов не поддерживаются.
- Аннотации не nil не поддерживаются.
Пример:
let jsonNode = parseJson(""" { "person": { "name": "Nimmer", "age": 21 }, "list": [1, 2, 3, 4] } """) type Person = object name: string age: int Data = object person: Person list: seq[int] var data = to(jsonNode, Data) doAssert data.person.name == "Nimmer" doAssert data.person.age == 21 doAssert data.list == @[1, 2, 3, 4]Исходный код Изменить proc toUgly(result: var string; node: JsonNode) {....raises: [], tags: [], forbids: [].}-
Преобразует
nodeв его JSON-представление, не заботясь о удобочитаемости. Предназначено для повышения производительности преобразования строки в$.JSON-представление хранится в переданной
resultЭто обеспечивает более высокую эффективность, чем процедура
Исходный код Изменитьpretty, так как она не пытается отформатировать результирующий JSON для удобочитаемости. proc `{}`(node: JsonNode; index: varargs[int]): JsonNode {....raises: [], tags: [], forbids: [].}- Перебирает узел и получает заданное значение. Если какой-либо из индексов не существует, возвращает
nil. Также возвращаетnilесли одна из промежуточных структур данных не является массивом. Исходный код Изменить proc `{}`(node: JsonNode; key: string): JsonNode {....raises: [], tags: [], forbids: [].}- Получает поле из
node. Еслиnodeимеет значение nil или не является объектом, или значение поkeyне существует, возвращает nil Исходный код Изменить proc `{}`(node: JsonNode; keys: varargs[string]): JsonNode {....raises: [], tags: [], forbids: [].}-
Перебирает узел и получает заданное значение. Если какой-либо из ключей не существует, возвращает
nil. Также возвращаетnilесли одна из промежуточных структур данных не является объектом.Эта процедура может использоваться для создания древовидных структур на лету (иногда называемых автовивификацией):
Пример:
var myjson = %* {"parent": {"child": {"grandchild": 1}}} doAssert myjson{"parent", "child", "grandchild"} == newJInt(1)Исходный код Изменить proc `{}=`(node: JsonNode; keys: varargs[string]; value: JsonNode) {. ...raises: [KeyError], tags: [], forbids: [].}- Перебирает узел и пытается установить значение в заданном месте на
value. Если какие-либо из ключей отсутствуют, они добавляются. Исходный код Изменить
Итераторы
iterator items(node: JsonNode): JsonNode {....raises: [], tags: [], forbids: [].}- Итератор для элементов
node.nodeдолжен быть JArray. Исходный код Изменить iterator keys(node: JsonNode): string {....raises: [], tags: [], forbids: [].}- Итератор для ключей в
node.nodeдолжен быть JObject. Исходный код Изменить iterator mitems(node: var JsonNode): var JsonNode {....raises: [], tags: [], forbids: [].}- Итератор для элементов
node.nodeдолжен быть JArray. Элементы могут быть изменены. Исходный код Изменить iterator mpairs(node: var JsonNode): tuple[key: string, val: var JsonNode] {. ...raises: [], tags: [], forbids: [].}- Итератор для дочерних элементов
node.nodeдолжен быть JObject. Значения могут быть изменены Исходный код Изменить iterator pairs(node: JsonNode): tuple[key: string, val: JsonNode] {....raises: [], tags: [], forbids: [].}- Итератор для дочерних элементов
node.nodeдолжен быть JObject. Исходный код Изменить iterator parseJsonFragments(s: Stream; filename: string = ""; rawIntegers = false; rawFloats = false): JsonNode {. ...raises: [IOError, OSError, IOError, OSError, JsonParsingError, ValueError], tags: [ReadIOEffect, WriteIOEffect], forbids: [].}- Парсит из потока
sвJsonNodes.filenameнужен только для красивых сообщений об ошибках. JSON-фрагменты разделены пробелами. Это может быть значительно быстрее, чем аналогичный циклfor x in splitWhitespace(s): yield parseJson(x). Закрывает потокsпосле завершения. ЕслиrawIntegersимеет значение true, целочисленные литералы не будут преобразовываться в полеJInt, а будут сохраняться как исходные числа черезJString. ЕслиrawFloatsимеет значение true, литералы с плавающей запятой не будут преобразовываться в полеJFloat, а будут сохраняться как исходные числа черезJString. Исходный код Изменить
Макросы
macro `%*`(x: untyped): untyped
- Преобразует выражение в JsonNode напрямую, без необходимости указывать
%для каждого элемента. Исходный код Изменить macro isRefSkipDistinct(arg: typed): untyped
- Только внутреннее использование, не использовать Исходный код Изменить
Шаблоны
template `%`(j: JsonNode): JsonNode
- Исходный код Изменить
© 2006–2024 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/json.html