This module implements a simple high performance JSON parser. JSON (JavaScript Object Notation) is a lightweight data-interchange format that is easy for humans to read and write (unlike XML). It is easy for machines to parse and generate. JSON is based on a subset of the JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999.
Usage example:
let small_json = """{"test": 1.3, "key2": true}""" jobj = parseJson(small_json) assert (jobj.kind == JObject)\ jobj["test"] = newJFloat(0.7) # create or update echo($jobj["test"].fnum) echo($jobj["key2"].bval) echo jobj{"missing key"}.getFNum(0.1) # read a float value using a default jobj{"a", "b", "c"} = newJFloat(3.3) # created nested keys
Results in:
1.3000000000000000e+00 true
This module can also be used to comfortably create JSON using the %* operator:
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
Types
JsonEventKind = enum jsonError, ## an error occurred during parsing jsonEof, ## end of file reached jsonString, ## a string literal jsonInt, ## an integer literal jsonFloat, ## a float literal jsonTrue, ## the value ``true`` jsonFalse, ## the value ``false`` jsonNull, ## the value ``null`` jsonObjectStart, ## start of an object: the ``{`` token jsonObjectEnd, ## end of an object: the ``}`` token jsonArrayStart, ## start of an array: the ``[`` token jsonArrayEnd ## start of an array: the ``]`` token
- enumeration of all events that may occur when parsing Source Edit
JsonError = enum errNone, ## no error errInvalidToken, ## invalid token errStringExpected, ## string expected errColonExpected, ## ``:`` expected errCommaExpected, ## ``,`` expected errBracketRiExpected, ## ``]`` expected errCurlyRiExpected, ## ``}`` expected errQuoteExpected, ## ``"`` or ``'`` expected errEOC_Expected, ## ``*/`` expected errEofExpected, ## EOF expected errExprExpected ## expr expected
- enumeration that lists all errors that can occur Source Edit
JsonParser = object of BaseLexer a: string tok: TokKind kind: JsonEventKind err: JsonError state: seq[ParserState] filename: string
- the parser object. Source Edit
JsonNodeKind = enum JNull, JBool, JInt, JFloat, JString, JObject, JArray
- possible JSON node types Source Edit
JsonNode = ref JsonNodeObj
- JSON node Source Edit
JsonNodeObj = object case kind*: JsonNodeKind of JString: str*: string of JInt: num*: BiggestInt of JFloat: fnum*: float of JBool: bval*: bool of JNull: nil of JObject: fields*: OrderedTable[string, JsonNode] of JArray: elems*: seq[JsonNode]
- Source Edit
JsonParsingError = object of ValueError
- is raised for a JSON error Source Edit
Procs
proc open(my: var JsonParser; input: Stream; filename: string) {.
raises: [Exception], tags: [ReadIOEffect].}- initializes the parser with an input stream. Filename is only used for nice error messages. Source Edit
proc close(my: var JsonParser) {.
inline, raises: [Exception], tags: [].}- closes the parser my and its associated input stream. Source Edit
proc str(my: JsonParser): string {.
inline, raises: [], tags: [].}- returns the character data for the events: jsonInt, jsonFloat, jsonString Source Edit
proc getInt(my: JsonParser): BiggestInt {.
inline, raises: [ValueError], tags: [].}- returns the number for the event: jsonInt Source Edit
proc getFloat(my: JsonParser): float {.
inline, raises: [ValueError], tags: [].}- returns the number for the event: jsonFloat Source Edit
proc kind(my: JsonParser): JsonEventKind {.
inline, raises: [], tags: [].}- returns the current event type for the JSON parser Source Edit
proc getColumn(my: JsonParser): int {.
inline, raises: [], tags: [].}- get the current column the parser has arrived at. Source Edit
proc getLine(my: JsonParser): int {.
inline, raises: [], tags: [].}- get the current line the parser has arrived at. Source Edit
proc getFilename(my: JsonParser): string {.
inline, raises: [], tags: [].}- get the filename of the file that the parser processes. Source Edit
proc errorMsg(my: JsonParser): string {.
raises: [ValueError], tags: [].}- returns a helpful error message for the event jsonError Source Edit
proc errorMsgExpected(my: JsonParser; e: string): string {.
raises: [ValueError], tags: [].}- returns an error message "e expected" in the same format as the other error messages Source Edit
proc next(my: var JsonParser) {.
raises: [Exception], tags: [ReadIOEffect].}- retrieves the first/next event. This controls the parser. Source Edit
proc raiseParseErr(p: JsonParser; msg: string) {.
noinline, noreturn, raises: [JsonParsingError, ValueError], tags: [].}- raises an EJsonParsingError exception. Source Edit
proc newJString(s: string): JsonNode {.
raises: [], tags: [].}- Creates a new JString JsonNode. Source Edit
proc newJInt(n: BiggestInt): JsonNode {.
raises: [], tags: [].}- Creates a new JInt JsonNode. Source Edit
proc newJFloat(n: float): JsonNode {.
raises: [], tags: [].}- Creates a new JFloat JsonNode. Source Edit
proc newJBool(b: bool): JsonNode {.
raises: [], tags: [].}- Creates a new JBool JsonNode. Source Edit
proc newJNull(): JsonNode {.
raises: [], tags: [].}- Creates a new JNull JsonNode. Source Edit
proc newJObject(): JsonNode {.
raises: [], tags: [].}- Creates a new JObject JsonNode Source Edit
proc newJArray(): JsonNode {.
raises: [], tags: [].}- Creates a new JArray JsonNode Source Edit
proc getStr(n: JsonNode; default: string = ""): string {.
raises: [], tags: [].}-
Retrieves the string value of a JString JsonNode.
Returns default if n is not a JString, or if n is nil.
Source Edit proc getNum(n: JsonNode; default: BiggestInt = 0): BiggestInt {.
raises: [], tags: [].}-
Retrieves the int value of a JInt JsonNode.
Returns default if n is not a JInt, or if n is nil.
Source Edit proc getFNum(n: JsonNode; default: float = 0.0'f64): float {.
raises: [], tags: [].}-
Retrieves the float value of a JFloat JsonNode.
Returns default if n is not a JFloat or JInt, or if n is nil.
Source Edit proc getBVal(n: JsonNode; default: bool = false): bool {.
raises: [], tags: [].}-
Retrieves the bool value of a JBool JsonNode.
Returns default if n is not a JBool, or if n is nil.
Source Edit proc getFields(n: JsonNode; default = initOrderedTable(4)): OrderedTable[string, JsonNode] {.
raises: [], tags: [].}-
Retrieves the key, value pairs of a JObject JsonNode.
Returns default if n is not a JObject, or if n is nil.
Source Edit proc getElems(n: JsonNode; default: seq[JsonNode] = @ []): seq[JsonNode] {.
raises: [], tags: [].}-
Retrieves the int value of a JArray JsonNode.
Returns default if n is not a JArray, or if n is nil.
Source Edit proc `%`(s: string): JsonNode {.
raises: [], tags: [].}- Generic constructor for JSON data. Creates a new JString JsonNode. Source Edit
proc `%`(n: BiggestInt): JsonNode {.
raises: [], tags: [].}- Generic constructor for JSON data. Creates a new JInt JsonNode. Source Edit
proc `%`(n: float): JsonNode {.
raises: [], tags: [].}- Generic constructor for JSON data. Creates a new JFloat JsonNode. Source Edit
proc `%`(b: bool): JsonNode {.
raises: [], tags: [].}- Generic constructor for JSON data. Creates a new JBool JsonNode. Source Edit
proc `%`(keyVals: openArray[tuple[key: string, val: JsonNode]]): JsonNode {.
raises: [], tags: [].}- Generic constructor for JSON data. Creates a new JObject JsonNode Source Edit
proc `%`[T](elements: openArray[T]): JsonNode
- Generic constructor for JSON data. Creates a new JArray JsonNode Source Edit
proc `%`[](o: object): JsonNode
- Generic constructor for JSON data. Creates a new JObject JsonNode Source Edit
proc `%`[](o: ref object): JsonNode
- Generic constructor for JSON data. Creates a new JObject JsonNode Source Edit
proc `==`(a, b: JsonNode): bool {.
raises: [KeyError], tags: [].}- Check two nodes for equality Source Edit
proc hash(n: JsonNode): Hash {.
raises: [Exception], tags: [RootEffect].}- Compute the hash for a JSON node Source Edit
proc hash(n: OrderedTable[string, JsonNode]): Hash {.
noSideEffect, raises: [Exception], tags: [RootEffect].}- Source Edit
proc len(n: JsonNode): int {.
raises: [], tags: [].}- If n is a JArray, it returns the number of elements. If n is a JObject, it returns the number of pairs. Else it returns 0. Source Edit
proc `[]`(node: JsonNode; name: string): JsonNode {.
inline, raises: [KeyError], tags: [].}-
Gets a field from a JObject, which must not be nil. If the value at name does not exist, raises KeyError.
Note: The behaviour of this procedure changed in version 0.14.0. To get a list of usages and to restore the old behaviour of this procedure, compile with the -d:nimJsonGet flag.
Source Edit proc `[]`(node: JsonNode; index: int): JsonNode {.
inline, raises: [], tags: [].}- Gets the node at index in an Array. Result is undefined if index is out of bounds, but as long as array bound checks are enabled it will result in an exception. Source Edit
proc hasKey(node: JsonNode; key: string): bool {.
raises: [], tags: [].}- Checks if key exists in node. Source Edit
proc contains(node: JsonNode; key: string): bool {.
raises: [], tags: [].}- Checks if key exists in node. Source Edit
proc contains(node: JsonNode; val: JsonNode): bool {.
raises: [KeyError], tags: [].}- Checks if val exists in array node. Source Edit
proc existsKey(node: JsonNode; key: string): bool {.
deprecated, raises: [], tags: [].}- Deprecated for hasKey Source Edit
proc add(father, child: JsonNode) {.
raises: [], tags: [].}- Adds child to a JArray node father. Source Edit
proc add(obj: JsonNode; key: string; val: JsonNode) {.
raises: [], tags: [].}- Sets a field from a JObject. Source Edit
proc `[]=`(obj: JsonNode; key: string; val: JsonNode) {.
inline, raises: [], tags: [].}- Sets a field from a JObject. Source Edit
proc `{}`(node: JsonNode; keys: varargs[string]): JsonNode {.
raises: [], tags: [].}- Traverses the node and gets the given value. If any of the keys do not exist, returns nil. Also returns nil if one of the intermediate data structures is not an object. Source Edit
proc getOrDefault(node: JsonNode; key: string): JsonNode {.
raises: [], tags: [].}- Gets a field from a node. If node is nil or not an object or value at key does not exist, returns nil Source Edit
proc `{}=`(node: JsonNode; keys: varargs[string]; value: JsonNode) {.
raises: [KeyError], tags: [].}- Traverses the node and tries to set the value at the given location to value. If any of the keys are missing, they are added. Source Edit
proc delete(obj: JsonNode; key: string) {.
raises: [IndexError], tags: [].}- Deletes obj[key]. Source Edit
proc copy(p: JsonNode): JsonNode {.
raises: [], tags: [].}- Performs a deep copy of a. Source Edit
proc escapeJson(s: string; result: var string) {.
raises: [], tags: [].}- Converts a string s to its JSON representation. Appends to result. Source Edit
proc escapeJson(s: string): string {.
raises: [], tags: [].}- Converts a string s to its JSON representation. Source Edit
proc pretty(node: JsonNode; indent = 2): string {.
raises: [], tags: [].}- Returns a JSON Representation of node, with indentation and on multiple lines. Source Edit
proc toUgly(result: var string; node: JsonNode) {.
raises: [], tags: [].}-
Converts node to its JSON Representation, without regard for human readability. Meant to improve $ string conversion performance.
JSON representation is stored in the passed result
This provides higher efficiency than the pretty procedure as it does not attempt to format the resulting JSON to make it human readable.
Source Edit proc `$`(node: JsonNode): string {.
raises: [], tags: [].}- Converts node to its JSON Representation on one line. Source Edit
proc parseJson(s: Stream; filename: string): JsonNode {.
raises: [Exception, Exception, ValueError, JsonParsingError], tags: [ReadIOEffect].}- Parses from a stream s into a JsonNode. filename is only needed for nice error messages. Source Edit
proc parseJson(buffer: string): JsonNode {.
raises: [Exception, ValueError, JsonParsingError], tags: [ReadIOEffect].}- Parses JSON from buffer. Source Edit
proc parseFile(filename: string): JsonNode {.
raises: [IOError, Exception, ValueError, JsonParsingError], tags: [ReadIOEffect].}- Parses file into a JsonNode. Source Edit
Iterators
iterator items(node: JsonNode): JsonNode {.
raises: [], tags: [].}- Iterator for the items of node. node has to be a JArray. Source Edit
iterator mitems(node: var JsonNode): var JsonNode {.
raises: [], tags: [].}- Iterator for the items of node. node has to be a JArray. Items can be modified. Source Edit
iterator pairs(node: JsonNode): tuple[key: string, val: JsonNode] {.
raises: [], tags: [].}- Iterator for the child elements of node. node has to be a JObject. Source Edit
iterator mpairs(node: var JsonNode): tuple[key: string, val: var JsonNode] {.
raises: [], tags: [].}- Iterator for the child elements of node. node has to be a JObject. Values can be modified Source Edit