Module json

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)
echo($jobj["test"].fnum)
echo($jobj["key2"].bval)

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

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
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
JsonParser = object of BaseLexer
  a: string
  tok: TTokKind
  kind: JsonEventKind
  err: JsonError
  state: seq[ParserState]
  filename: string
the parser object.   Source
JsonNodeKind = enum 
  JNull, JBool, JInt, JFloat, JString, JObject, JArray
possible JSON node types   Source
JsonNode = ref JsonNodeObj
JSON node   Source
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*: seq[tuple[key: string, val: JsonNode]]

  of JArray: 
      elems*: seq[JsonNode]

  
  Source
JsonParsingError = object of ValueError
is raised for a JSON error   Source

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
proc close(my: var JsonParser) {.inline, raises: [Exception], tags: [].}
closes the parser my and its associated input stream.   Source
proc str(my: JsonParser): string {.inline, raises: [], tags: [].}
returns the character data for the events: jsonInt, jsonFloat, jsonString   Source
proc getInt(my: JsonParser): BiggestInt {.inline, raises: [ValueError], tags: [].}
returns the number for the event: jsonInt   Source
proc getFloat(my: JsonParser): float {.inline, raises: [ValueError], tags: [].}
returns the number for the event: jsonFloat   Source
proc kind(my: JsonParser): JsonEventKind {.inline, raises: [], tags: [].}
returns the current event type for the JSON parser   Source
proc getColumn(my: JsonParser): int {.inline, raises: [], tags: [].}
get the current column the parser has arrived at.   Source
proc getLine(my: JsonParser): int {.inline, raises: [], tags: [].}
get the current line the parser has arrived at.   Source
proc getFilename(my: JsonParser): string {.inline, raises: [], tags: [].}
get the filename of the file that the parser processes.   Source
proc errorMsg(my: JsonParser): string {.raises: [ValueError], tags: [].}
returns a helpful error message for the event jsonError   Source
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
proc next(my: var JsonParser) {.raises: [Exception], tags: [ReadIOEffect].}
retrieves the first/next event. This controls the parser.   Source
proc raiseParseErr(p: JsonParser; msg: string) {.noinline, noreturn, 
    raises: [JsonParsingError, ValueError], tags: [].}
raises an EJsonParsingError exception.   Source
proc newJString(s: string): JsonNode {.raises: [], tags: [].}
Creates a new JString JsonNode.   Source
proc newJInt(n: BiggestInt): JsonNode {.raises: [], tags: [].}
Creates a new JInt JsonNode.   Source
proc newJFloat(n: float): JsonNode {.raises: [], tags: [].}
Creates a new JFloat JsonNode.   Source
proc newJBool(b: bool): JsonNode {.raises: [], tags: [].}
Creates a new JBool JsonNode.   Source
proc newJNull(): JsonNode {.raises: [], tags: [].}
Creates a new JNull JsonNode.   Source
proc newJObject(): JsonNode {.raises: [], tags: [].}
Creates a new JObject JsonNode   Source
proc newJArray(): JsonNode {.raises: [], tags: [].}
Creates a new JArray JsonNode   Source
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.

  Source
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.

  Source
proc getFNum(n: JsonNode; default: float = 0.0): float {.raises: [], tags: [].}

Retrieves the float value of a JFloat JsonNode.

Returns default if n is not a JFloat.

  Source
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.

  Source
proc getFields(n: JsonNode; 
               default: seq[tuple[key: string, val: JsonNode]] = @ []): seq[
    tuple[key: string, val: JsonNode]] {.raises: [], tags: [].}

Retrieves the key, value pairs of a JObject JsonNode.

Returns default if n is not a JObject.

  Source
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.

  Source
proc `%`(s: string): JsonNode {.raises: [], tags: [].}
Generic constructor for JSON data. Creates a new JString JsonNode.   Source
proc `%`(n: BiggestInt): JsonNode {.raises: [], tags: [].}
Generic constructor for JSON data. Creates a new JInt JsonNode.   Source
proc `%`(n: float): JsonNode {.raises: [], tags: [].}
Generic constructor for JSON data. Creates a new JFloat JsonNode.   Source
proc `%`(b: bool): JsonNode {.raises: [], tags: [].}
Generic constructor for JSON data. Creates a new JBool JsonNode.   Source
proc `%`(keyVals: openArray[tuple[key: string, val: JsonNode]]): JsonNode {.
    raises: [], tags: [].}
Generic constructor for JSON data. Creates a new JObject JsonNode   Source
proc `%`(elements: openArray[JsonNode]): JsonNode {.raises: [], tags: [].}
Generic constructor for JSON data. Creates a new JArray JsonNode   Source
proc `==`(a, b: JsonNode): bool {.raises: [], tags: [].}
Check two nodes for equality   Source
proc hash(n: JsonNode): THash {.raises: [], tags: [].}
Compute the hash for a JSON node   Source
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
proc `[]`(node: JsonNode; name: string): JsonNode {.raises: [], tags: [].}
Gets a field from a JObject, which must not be nil. If the value at name does not exist, returns nil   Source
proc `[]`(node: JsonNode; index: int): JsonNode {.raises: [], tags: [].}
Gets the node at index in an Array. Result is undefined if index is out of bounds   Source
proc hasKey(node: JsonNode; key: string): bool {.raises: [], tags: [].}
Checks if key exists in node.   Source
proc existsKey(node: JsonNode; key: string): bool {.deprecated, raises: [], 
    tags: [].}
Deprecated for hasKey   Source
proc add(father, child: JsonNode) {.raises: [], tags: [].}
Adds child to a JArray node father.   Source
proc add(obj: JsonNode; key: string; val: JsonNode) {.raises: [], tags: [].}
Adds (key, val) pair to the JObject node obj. For speed reasons no check for duplicate keys is performed! But []= performs the check.   Source
proc `[]=`(obj: JsonNode; key: string; val: JsonNode) {.raises: [], tags: [].}
Sets a field from a JObject. Performs a check for duplicate keys.   Source
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
proc `{}=`(node: JsonNode; keys: varargs[string]; value: JsonNode) {.raises: [], 
    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
proc delete(obj: JsonNode; key: string) {.raises: [IndexError], tags: [].}
Deletes obj[key] preserving the order of the other (key, value)-pairs.   Source
proc copy(p: JsonNode): JsonNode {.raises: [], tags: [].}
Performs a deep copy of a.   Source
proc escapeJson(s: string): string {.raises: [], tags: [].}
Converts a string s to its JSON representation.   Source
proc pretty(node: JsonNode; indent = 2): string {.raises: [], tags: [].}
Converts node to its JSON Representation, with indentation and on multiple lines.   Source
proc `$`(node: JsonNode): string {.raises: [], tags: [].}
Converts node to its JSON Representation on one line.   Source
proc parseJson(s: Stream; filename: string): JsonNode {.
    raises: [Exception, ValueError, JsonParsingError], tags: [ReadIOEffect].}
Parses from a stream s into a JsonNode. filename is only needed for nice error messages.   Source
proc parseJson(buffer: string): JsonNode {.
    raises: [Exception, ValueError, JsonParsingError], tags: [ReadIOEffect].}
Parses JSON from buffer.   Source
proc parseFile(filename: string): JsonNode {.
    raises: [IOError, Exception, ValueError, JsonParsingError], 
    tags: [ReadIOEffect].}
Parses file into a JsonNode.   Source

Iterators

iterator items(node: JsonNode): JsonNode {.raises: [], tags: [].}
Iterator for the items of node. node has to be a JArray.   Source
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
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
iterator mpairs(node: var JsonNode): var tuple[key: string, val: JsonNode] {.
    raises: [], tags: [].}
Iterator for the child elements of node. node has to be a JObject. Items can be modified   Source

Macros

macro `%*`(x: expr): expr
Convert an expression to a JsonNode directly, without having to specify % for every element.   Source