diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2014-05-31 20:35:26 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2014-05-31 20:35:26 +0200 |
commit | 726003ac528787ee597ec5e121ae74fa795c31c0 (patch) | |
tree | 2204198678a6030caaca63487be6f56561d0189b /lib/pure | |
parent | 794b035e8912343a6a7a366cc5faa50e086a516a (diff) | |
parent | 08a76f04664020e7bdf99f3732a808d40c37350d (diff) | |
download | Nim-726003ac528787ee597ec5e121ae74fa795c31c0.tar.gz |
Merge pull request #1089 from flaviut/jsonchange
Allow for nil chaining in JSON and require an exception on out-of-bounds indexing
Diffstat (limited to 'lib/pure')
-rw-r--r-- | lib/pure/json.nim | 49 |
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() |