summary refs log tree commit diff stats
path: root/lib/pure
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure')
-rw-r--r--lib/pure/json.nim49
1 files changed, 47 insertions, 2 deletions
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 4250847e5..306a8a2e2 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -629,7 +629,9 @@ proc len*(n: PJsonNode): int =
   else: discard
 
 proc `[]`*(node: PJsonNode, name: string): PJsonNode =
-  ## Gets a field from a `JObject`. Returns nil if the key is not found.
+  ## Gets a field from a `JObject`, which must not be nil.
+  ## If the value at `name` does not exist, returns nil
+  assert(node != nil)
   assert(node.kind == JObject)
   for key, item in items(node.fields):
     if key == name:
@@ -637,8 +639,10 @@ proc `[]`*(node: PJsonNode, name: string): PJsonNode =
   return nil
   
 proc `[]`*(node: PJsonNode, index: int): PJsonNode =
-  ## Gets the node at `index` in an Array.
+  ## Gets the node at `index` in an Array. Result is undefined if `index`
+  ## is out of bounds
   assert(node.kind == JArray)
+  assert(node != nil)
   return node.elems[index]
 
 proc hasKey*(node: PJsonNode, key: string): bool =
@@ -671,6 +675,25 @@ proc `[]=`*(obj: PJsonNode, key: string, val: PJsonNode) =
       return
   obj.fields.add((key, val))
 
+proc `{}`*(node: PJsonNode, names: varargs[string]): PJsonNode =
+  ## Transverses the node and gets the given value. If any of the
+  ## names does not exist, returns nil
+  result = node
+  for name in names:
+    result = result[name]
+    if isNil(result):
+      return nil
+
+proc `{}=`*(node: PJsonNode, names: varargs[string], value: PJsonNode) =
+  ## Transverses the node and tries to set the value at the given location
+  ## to `value` If any of the names are missing, they are added
+  var node = node
+  for i in 0..(names.len-2):
+    if isNil(node[names[i]]):
+      node[names[i]] = newJObject()
+    node = node[names[i]]
+  node[names[names.len-1]] = value
+
 proc delete*(obj: PJsonNode, key: string) =
   ## Deletes ``obj[key]`` preserving the order of the other (key, value)-pairs.
   assert(obj.kind == JObject)
@@ -996,6 +1019,28 @@ when isMainModule:
     raise newException(EInvalidValue, "That line was expected to fail")
   except EInvalidIndex: echo()
 
+  let testJson = parseJson"""{ "a": [1, 2, 3, 4], "b": "asd" }"""
+  # nil passthrough
+  assert(testJson{"doesnt_exist", "anything"} == nil)
+  testJson{["c", "d"]} = %true
+  assert(testJson["c"]["d"].bval)
+
+  # Bounds checking
+  try:
+    let a = testJson["a"][9]
+    assert(false, "EInvalidIndex not thrown")
+  except EInvalidIndex:
+    discard
+  try:
+    let a = testJson["a"][-1]
+    assert(false, "EInvalidIndex not thrown")
+  except EInvalidIndex:
+    discard
+  try:
+    assert(testJson["a"][0].num == 1, "Index doesn't correspond to its value")
+  except:
+    assert(false, "EInvalidIndex thrown for valid index")
+
   discard """
   while true:
     var json = stdin.readLine()