Process branch data by 'jsondata.JSONData' ****************************************** The module jsondata.JSONData provides for the operations on data structures, whereas it relies for the syntax operations on 'json' and compatible compatible packages. The design is implemented as a container class providing high level structure operations and the access to the data structures by the standard by low-level native Python operations. Provided basic operations are: * **native access attributes**: The node addresses for the native access to the JSON in-memory representation. The data format is compatible to the packages 'json' and 'jsonschema', e.g. also to 'ujson'. Thus provides native Python access performance. * **branch operations**: Handle complete sub structures as logical branches of a main JSON document. The interface is designed in accordance to RFC6902 with extension for Python specifics. * **tree utilities**: Generic tree functions for the provided in-memory representation by 'json' and 'jsonschema'. Syntax Elements =============== The current release provides the following operators for the class 'JSONPointer'. Native JSON representation access attributes:: attr := data, schema Branch operations(branch_<ops>), see RFC6902:: ops := add | copy | create | move | remove | replace test Branch operators:: ops := '[]' | '()' Generic operations:: ops := getTreeDiff | getPointerPath | getValueNode Examples ======== Examples for the provided basic calculations are: Create,Add ---------- * **Branch Operations - create a JSON document, add and create branches**:: import jsondata.JSONData import jsondata.JSONPointer # JSON document jdata = { 'a': { 'b': { 'c': 2, 'd': 3 } } } # JSON branch with array arr = { 'e': { 'lx': [] } } # Branch elements for array ai0 = { 'v0': 100} ai1 = { 'v1': 200} # JSON branch with object obj = { 'f': { 'ox': {} } } # Branch elements for object l0 = { 'o0': 10} l1 = { 'o1': 20} # JSON in-memory document D = JSONData(jdata) # Add a branch with an array D.branch_add(JSONPointer('/a/b'),'e',arr['e']) # Add a items to the new array # Remark: for '-' refer to RFC6901 - array-index D.branch_add(JSONPointer('/a/b/e/lx'),'-',ai0) D.branch_add(JSONPointer('/a/b/e/lx'),'-',ai1) # Add a branch with an object D.branch_add(JSONPointer('/a/b'),'f',obj['f']) # Add an item to the new object, from an object D.branch_add(JSONPointer('/a/b/f/ox'),'v0',ai0['v0']) # Add an item to the new object ai1v1 = ai1['v1'] D.branch_add(JSONPointer('/a/b/f/ox'),'v1',ai1v1) nodex = JSONPointer(['a','b']).get_node(D.data) ret = D.branch_create(nodex, ['g','x'], {}) ret['x0'] = 22 ret['x1'] = 33 ret = D.branch_create(nodex, ['g','x','xlst'], []) ret.append('first') ret.append('second') rdata = {'a': {'b': {'c': 2, 'e': {'lx': [{'v0': 100}, {'v1': 200}]}, 'd': 3, u'g': {u'x': {'x0': 22, 'x1': 33, u'xlst': ['first', 'second']}}, 'f': {'ox': {'v0': 100, 'v1': 200}}}} } assert D.data == rdata print D prints the result:: { "a": { "b": { "c": 2, "e": { "lx": [ { "v0": 100 }, { "v1": 200 } ] }, "d": 3, "g": { "x": { "x0": 22, "x1": 33, "xlst": [ "first", "second" ] } }, "f": { "ox": { "v0": 100, "v1": 200 } } } } } Access values ------------- * **Branch Operations - various access to values**:: print D(['a', 'b', 'c']) print D(JSONPointer('/a/b/c')) print D('/a/b/c') n = JSONPointer('/a/b/c').get_node(D.data,True) print n['c'] n = JSONPointer('/a/b/c').get_node(D.data,True) px = D.getPointerPath(n, D.data)[0] px.append('c') print D(JSONPointer(px)) prints the result:: 2 2 2 2 2 Move ---- * **Branch Operations - move a branch**:: target = JSONPointer('/a/b/new') source = JSONPointer('/a/b/c') print D(source) n = D('/a/b') n['c'] = 77 targetnode = target.get_node(D.data,True) sourcenode = source.get_node(D.data,True) D.branch_move(targetnode, 'new', sourcenode, 'c') print D(target) # check new position assert D(target) == 77 # validate old position try: x = D('/a/b/c') except JSONPointerException as e: pass else: raise prints the result:: 2 77 Remove ------ * **Branch Operations - remove a branch**:: # get a pointer target = JSONPointer('/a/b/new') # get the parent node for the pointer targetnode = target.get_node(D.data,True) # verify existence x = D('/a/b/new') assert x == 77 # remove item D.branch_remove(targetnode, 'new') # validate old position try: x = D('/a/b/new') except JSONPointerException as e: pass else: raise pass Replace ------- * **Branch Operations - replace a branch**:: # does not verify childnode, when 'parent=True' <=> 'new' does no longer exist targetnode = JSONPointer('/a/b/new').get_node(D.data,True) # new item sourcenode = {'alternate': 4711 } # replace old by new item ret = D.branch_replace(targetnode, 'f', sourcenode) assert ret == True # verify new item x = D('/a/b/f/alternate') assert x == 4711 Test ---- * **Branch Operations - test value**:: # variant 0 ret = D.branch_test(JSONPointer('/a/b/f/alternate').get_node_or_value(D.data), 4711) assert ret == True # variant 1 ret = D.branch_test(JSONPointer('/a/b/f/alternate')(D.data), 4711) assert ret == True # variant 2 p = JSONPointer('/a/b/f/alternate') ret = D.branch_test(p(D.data), 4711) assert ret == True Copy ---- * **Branch Operations - copy branch**:: # JSON branch with array arr = { 'cpy': { 'cx': [ 2, 3, 4, ] } } # Copy a branch with an array D.branch_copy(JSONPointer('/a/b'),'cpy',arr['cpy'])