summary refs log tree commit diff stats
path: root/lib/pure/json.nim
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2014-07-15 01:42:19 +0200
committerAndreas Rumpf <rumpf_a@web.de>2014-07-15 01:42:19 +0200
commit18ded6c23d72cd21fa0aa10ff61dc6f9af40832c (patch)
tree5d681c9835f01019e8ae83e14c0cd49d1a6c0d38 /lib/pure/json.nim
parent687a1b7de4c006750274fb046a10f08d38c22f5a (diff)
parent41bb0bf9dcccdfcebdb0f823fea8b2853b89ea4e (diff)
downloadNim-18ded6c23d72cd21fa0aa10ff61dc6f9af40832c.tar.gz
Merge pull request #1363 from Araq/devel
Merge devel into master
Diffstat (limited to 'lib/pure/json.nim')
-rw-r--r--lib/pure/json.nim85
1 files changed, 83 insertions, 2 deletions
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 4250847e5..508e564c5 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -619,6 +619,44 @@ proc `%`*(elements: openArray[PJsonNode]): PJsonNode =
   newSeq(result.elems, elements.len)
   for i, p in pairs(elements): result.elems[i] = p
 
+proc `==`* (a,b: PJsonNode): bool =
+  ## Check two nodes for equality
+  if a.kind != b.kind: false
+  else:
+    case a.kind
+    of JString:
+      a.str == b.str
+    of JInt:
+      a.num == b.num
+    of JFloat:
+      a.fnum == b.fnum
+    of JBool:
+      a.bval == b.bval
+    of JNull:
+      true
+    of JArray:
+      a.elems == b.elems
+    of JObject:
+      a.fields == b.fields
+
+proc hash* (n:PJsonNode): THash =
+  ## Compute the hash for a JSON node
+  case n.kind
+  of JArray:
+    result = hash(n.elems)
+  of JObject:
+    result = hash(n.fields)
+  of JInt:
+    result = hash(n.num)
+  of JFloat:
+    result = hash(n.fnum)
+  of JBool:
+    result = hash(n.bval.int)
+  of JString:
+    result = hash(n.str)
+  of JNull:
+    result = hash(0)
+
 proc len*(n: PJsonNode): int = 
   ## If `n` is a `JArray`, it returns the number of elements.
   ## If `n` is a `JObject`, it returns the number of pairs.
@@ -629,7 +667,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(not isNil(node))
   assert(node.kind == JObject)
   for key, item in items(node.fields):
     if key == name:
@@ -637,7 +677,9 @@ 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(not isNil(node))
   assert(node.kind == JArray)
   return node.elems[index]
 
@@ -671,6 +713,23 @@ proc `[]=`*(obj: PJsonNode, key: string, val: PJsonNode) =
       return
   obj.fields.add((key, val))
 
+proc `{}`*(node: PJsonNode, key: string): PJsonNode =
+  ## Transverses the node and gets the given value. If any of the
+  ## names does not exist, returns nil
+  result = node
+  if isNil(node): return nil
+  result = result[key]
+
+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 +1055,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"}.isNil)
+  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()