Source Edit

This module implements a hookable (de)serialization for arbitrary types using JSON. Design goal: avoid importing modules where a custom serialization is needed; see strtabs.fromJsonHook,toJsonHook for an example.

Example:

  1. import std/jsonutils
  2. import std/[strtabs,json]
  3. type Foo = ref object
  4. t: bool
  5. z1: int8
  6. let a = (1.5'f32, (b: "b2", a: "a2"), 'x', @[Foo(t: true, z1: -3), nil], [{"name": "John"}.newStringTable])
  7. let j = a.toJson
  8. assert j.jsonTo(typeof(a)).toJson == j
  9. assert $[NaN, Inf, -Inf, 0.0, -0.0, 1.0, 1e-2].toJson == """["nan","inf","-inf",0.0,-0.0,1.0,0.01]"""
  10. assert 0.0.toJson.kind == JFloat
  11. assert Inf.toJson.kind == JString

Imports

json, strutils, tables, sets, strtabs, options, strformat, macros, enumutils, typetraits

Types

  1. EnumMode = enum
  2. joptEnumOrd, joptEnumSymbol, joptEnumString

Source Edit

  1. Joptions = object
  2. allowExtraKeys*: bool ## If `true` Nim's object to which the JSON is parsed is not required to
  3. ## have a field for every JSON key.
  4. allowMissingKeys*: bool ## If `true` Nim's object to which JSON is parsed is allowed to have
  5. ## fields without corresponding JSON keys.

Options controlling the behavior of fromJson. Source Edit

  1. JsonNodeMode = enum
  2. joptJsonNodeAsRef, ## returns the ref as is
  3. joptJsonNodeAsCopy, ## returns a deep copy of the JsonNode
  4. joptJsonNodeAsObject ## treats JsonNode as a regular ref object

controls toJson for JsonNode types Source Edit

  1. ToJsonOptions = object
  2. enumMode*: EnumMode
  3. jsonNodeMode*: JsonNodeMode

Source Edit

Procs

  1. proc fromJson[T](a: var T; b: JsonNode; opt = Joptions())

Source Edit

  1. proc fromJsonHook(a: var StringTableRef; b: JsonNode) {.
  2. ...raises: [ValueError, KeyError, JsonKindError], tags: [RootEffect],
  3. forbids: [].}

Enables fromJson for StringTableRef type.

See also:

Example:

  1. import std/[strtabs, json]
  2. var t = newStringTable(modeCaseSensitive)
  3. let jsonStr = """{"mode": 0, "table": {"name": "John", "surname": "Doe"}}"""
  4. fromJsonHook(t, parseJson(jsonStr))
  5. assert t[] == newStringTable("name", "John", "surname", "Doe",
  6. modeCaseSensitive)[]

Source Edit

  1. proc fromJsonHook[A](s: var SomeSet[A]; jsonNode: JsonNode; opt = Joptions())

Enables fromJson for HashSet and OrderedSet types.

See also:

Example:

  1. import std/[sets, json]
  2. var foo: tuple[hs: HashSet[string], os: OrderedSet[string]]
  3. fromJson(foo, parseJson("""
  4. {"hs": ["hash", "set"], "os": ["ordered", "set"]}"""))
  5. assert foo.hs == ["hash", "set"].toHashSet
  6. assert foo.os == ["ordered", "set"].toOrderedSet

Source Edit

  1. proc fromJsonHook[K: string | cstring; V](
  2. t: var (Table[K, V] | OrderedTable[K, V]); jsonNode: JsonNode;
  3. opt = Joptions())

Enables fromJson for Table and OrderedTable types.

See also:

Example:

  1. import std/[tables, json]
  2. var foo: tuple[t: Table[string, int], ot: OrderedTable[string, int]]
  3. fromJson(foo, parseJson("""
  4. {"t":{"two":2,"one":1},"ot":{"one":1,"three":3}}"""))
  5. assert foo.t == [("one", 1), ("two", 2)].toTable
  6. assert foo.ot == [("one", 1), ("three", 3)].toOrderedTable

Source Edit

  1. proc fromJsonHook[T](self: var Option[T]; jsonNode: JsonNode; opt = Joptions())

Enables fromJson for Option types.

See also:

Example:

  1. import std/[options, json]
  2. var opt: Option[string]
  3. fromJsonHook(opt, parseJson("\"test\""))
  4. assert get(opt) == "test"
  5. fromJson(opt, parseJson("null"))
  6. assert isNone(opt)

Source Edit

  1. proc initToJsonOptions(): ToJsonOptions {....raises: [], tags: [], forbids: [].}

initializes ToJsonOptions with sane options. Source Edit

  1. proc jsonTo(b: JsonNode; T: typedesc; opt = Joptions()): T:type

reverse of toJson Source Edit

  1. proc toJson[T](a: T; opt = initToJsonOptions()): JsonNode

serializes a to json; uses toJsonHook(a: T) if it’s in scope to customize serialization, see strtabs.toJsonHook for an example.

Note: With -d:nimPreviewJsonutilsHoleyEnum, toJson now can serialize/deserialize holey enums as regular enums (via ord) instead of as strings. It is expected that this behavior becomes the new default in upcoming versions.

Source Edit

  1. proc toJsonHook(a: StringTableRef): JsonNode {....raises: [], tags: [], forbids: [].}

Enables toJson for StringTableRef type.

See also:

Example:

  1. import std/[strtabs, json]
  2. let t = newStringTable("name", "John", "surname", "Doe", modeCaseSensitive)
  3. let jsonStr = """{"mode": "modeCaseSensitive",
  4. "table": {"name": "John", "surname": "Doe"}}"""
  5. assert toJson(t) == parseJson(jsonStr)

Source Edit

  1. proc toJsonHook[A](s: SomeSet[A]; opt = initToJsonOptions()): JsonNode

Enables toJson for HashSet and OrderedSet types.

See also:

Example:

  1. import std/[sets, json]
  2. let foo = (hs: ["hash"].toHashSet, os: ["ordered", "set"].toOrderedSet)
  3. assert $toJson(foo) == """{"hs":["hash"],"os":["ordered","set"]}"""

Source Edit

  1. proc toJsonHook[K: string | cstring; V](t: (Table[K, V] | OrderedTable[K, V]);
  2. opt = initToJsonOptions()): JsonNode

Enables toJson for Table and OrderedTable types.

See also:

Example:

  1. import std/[tables, json, sugar]
  2. let foo = (
  3. t: [("two", 2)].toTable,
  4. ot: [("one", 1), ("three", 3)].toOrderedTable)
  5. assert $toJson(foo) == """{"t":{"two":2},"ot":{"one":1,"three":3}}"""
  6. # if keys are not string|cstring, you can use this:
  7. let a = {10: "foo", 11: "bar"}.newOrderedTable
  8. let a2 = collect: (for k,v in a: (k,v))
  9. assert $toJson(a2) == """[[10,"foo"],[11,"bar"]]"""

Source Edit

  1. proc toJsonHook[T](self: Option[T]; opt = initToJsonOptions()): JsonNode

Enables toJson for Option types.

See also:

Example:

  1. import std/[options, json]
  2. let optSome = some("test")
  3. assert $toJson(optSome) == "\"test\""
  4. let optNone = none[string]()
  5. assert $toJson(optNone) == "null"

Source Edit