JSONData - RFC7159 et al.

This howto focussed on applied code examples.

Branch Operations

The branch operations provide for the operations of higher level of structured data. These are also the technical base for the standards conformant operations in accordance to RFC6902 and RFC6901, see JSONPatch - RFC6902 and see JSONPointer - RFC6901 .

Create Branch

Create a JSON document consisting of a new branch JSONData.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData

# JSON in-memory document
D = JSONData(
        { 'a': { 'b': { 'c': 2, 'd': 3 } } }
    )

# print structure
print(D)

prints the result by str:

1
2
3
4
5
6
7
8
{
    "a": {
        "b": {
            "c": 2,
            "d": 3
        }
    }
}

or by repr:

1
{'a': {'b': {'c': 2, 'd': 3}}}

Add Branch

Object with Key

Create a JSON document and add a branch, see also OP_IADD

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
D = JSONData({'a': {'b': {'c': 2, 'd': 3}}})
source = {'lx': [{'v0': 100}, {'v1': 200}]}

# JSON branch with array
D.branch_add(source, D, 'e')

print(D)
# print(repr(D))

prints the result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
    "a": {
        "b": {
            "c": 2,
            "d": 3
        }
    },
    "e": {
        "lx": [
            {
                "v0": 100
            },
            {
                "v1": 200
            }
        ]
    }
}

Object without Key

Create a JSON document and add a branch, see also OP_IADD

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
D = JSONData({'a': {'b': {'c': 2, 'd': 3}}})
source = { 'e': {'lx': [{'v0': 100}, {'v1': 200}]}}

# JSON branch with array
D.branch_add(source, D)

print(D)
# print(repr(D))

prints the result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
    "a": {
        "b": {
            "c": 2,
            "d": 3
        }
    },
    "e": {
        "lx": [
            {
                "v0": 100
            },
            {
                "v1": 200
            }
        ]
    }
}

Move

Object Attribute

Call with key

Move an attribute branch within a JSON document.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
D = JSONData({'a': {'b': {'c': 2, 'd': 3}}, 'e': {'lx': [{'v0': 100}, {'v1': 200}]}})

target = JSONPointer('/a/b')
source = JSONPointer('/a/b/c')

D.branch_move(source, target, 'new')

print(D)
#print(repr(D))

prints the result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
    "a": {
        "b": {
            "d": 3,
            "new": 2
        }
    },
    "e": {
        "lx": [
            {
                "v0": 100
            },
            {
                "v1": 200
            }
        ]
    }
}
Call without key

Move an attribute branch within a JSON document.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
D = JSONData({'a': {'b': {'c': 2, 'd': 3}}, 'e': {'lx': [{'v0': 100}, {'v1': 200}]}})

target = JSONPointer('/a/b/new')
source = JSONPointer('/a/b/c')

D.branch_move(source, target)

print(D)
#print(repr(D))

prints the result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
    "a": {
        "b": {
            "d": 3,
            "new": 2
        }
    },
    "e": {
        "lx": [
            {
                "v0": 100
            },
            {
                "v1": 200
            }
        ]
    }
}

Array Element

Call with key

Move an array element within a JSON document.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
D = JSONData({'a': {'b': {'c': 2, 'd': 3}}, 'e': {'lx': [{'v0': 100}, {'v1': 200}]}})

target = JSONPointer('/e/lx')
source = JSONPointer('/e/lx/0')

D.branch_move(source, target, '-')

print(D)
#print(repr(D))

prints the result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
    "a": {
        "b": {
            "c": 2,
            "d": 3
        }
    },
    "e": {
        "lx": [
            {
                "v1": 200
            },
            {
                "v0": 100
            }
        ]
    }
}
Call without key

Move an array element within a JSON document.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
D = JSONData({'a': {'b': {'c': 2, 'd': 3}}, 'e': {'lx': [{'v0': 100}, {'v1': 200}]}})

target = JSONPointer('/e/lx/-')
source = JSONPointer('/e/lx/0')

D.branch_move(source, target)

print(D)
#print(repr(D))

prints the result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
    "a": {
        "b": {
            "c": 2,
            "d": 3
        }
    },
    "e": {
        "lx": [
            {
                "v1": 200
            },
            {
                "v0": 100
            }
        ]
    }
}

Remove Branch

From Object

Call with key

Remove a branch or item within a container by it’s key, convenient for loops.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
D = JSONData({'a': {'b': {'c': 2, 'd': 3}}, 'e': {'lx': [{'v0': 100}, {'v1': 200}]}})

target = JSONPointer('/a/b')

D.branch_remove(target, 'c')

print(D)
#print(repr(D))

prints the result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
    "a": {
        "b": {
            "d": 3
        }
    },
    "e": {
        "lx": [
            {
                "v0": 100
            },
            {
                "v1": 200
            }
        ]
    }
}
Call without key

Remove a branch or item by it’s path only.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
D = JSONData({'a': {'b': {'c': 2, 'd': 3}}, 'e': {'lx': [{'v0': 100}, {'v1': 200}]}})

target = JSONPointer('/a/b/c')

D.branch_remove(target)

print(D)
#print(repr(D))

prints the result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
    "a": {
        "b": {
            "d": 3
        }
    },
    "e": {
        "lx": [
            {
                "v0": 100
            },
            {
                "v1": 200
            }
        ]
    }
}

From Array

Call with key

Remove a branch or item within a container by it’s key, convenient for loops.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
D = JSONData({'a': {'b': {'c': 2, 'd': 3}}, 'e': {'lx': [{'v0': 100}, {'v1': 200}]}})

target = JSONPointer('/e/lx')

D.branch_remove(target, 1)

print(D)
#print(repr(D))

prints the result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
    "a": {
        "b": {
            "c": 2,
            "d": 3
        }
    },
    "e": {
        "lx": [
            {
                "v0": 100
            }
        ]
    }
}
Call without key

Remove a branch or item by it’s path only.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
D = JSONData({'a': {'b': {'c': 2, 'd': 3}}, 'e': {'lx': [{'v0': 100}, {'v1': 200}]}})

target = JSONPointer('/e/lx/1')

D.branch_remove(target)

print(D)
#print(repr(D))

prints the result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
    "a": {
        "b": {
            "c": 2,
            "d": 3
        }
    },
    "e": {
        "lx": [
            {
                "v0": 100
            }
        ]
    }
}

Similar calls with reverse index:

1
2
target = JSONPointer('/e/lx/-1')
target = JSONPointer('/e/lx/-2')

and special index rfc6901:

1
target = JSONPointer('/e/lx/-')

Replace

Object Attribute

Replace an attribute branch within a JSON document.

Replace a branch.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
D = JSONData({'a': {'b': {'c': 2, 'd': 3}}, 'e': {'lx': [{'v0': 100}, {'v1': 200}]}})


# does not verify childnode, when 'parent=True' <=> 'new' does no longer exist
targetnode = JSONPointer('/a/b').get_path_list()

# new item
sourcenode = {'alternate': 4711 }

# replace old by new item
ret = D.branch_replace(sourcenode, targetnode, 'c')
assert ret == True

# verify new item
x = D('/a/b/c/alternate')  # see JSONData.__call__
assert x == 4711

print(D)

prints the result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{
    "a": {
        "b": {
            "c": {
                "alternate": 4711
            },
            "d": 3
        }
    },
    "e": {
        "lx": [
            {
                "v0": 100
            },
            {
                "v1": 200
            }
        ]
    }
}

Array Element

Move an array element within a JSON document.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
D = JSONData({'a': {'b': {'c': 2, 'd': 3}}, 'e': {'lx': [{'v0': 100}, {'v1': 200}]}})


# does not verify childnode, when 'parent=True' <=> 'new' does no longer exist
targetnode = JSONPointer('/e/lx/0').get_path_list()

# new item
sourcenode = {'alternate': 4711 }

# replace old by new item
ret = D.branch_replace(sourcenode, targetnode)
assert ret == True

# verify new item
x = D('/e/lx/0/alternate')  # see JSONData.__call__
assert x == 4711

print(D)

prints the result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
    "a": {
        "b": {
            "c": 2,
            "d": 3
        }
    },
    "e": {
        "lx": [
            {
                "alternate": 4711
            },
            {
                "v1": 200
            }
        ]
    }
}

Branch Algebra

RFC7159 Examples

Create Objects

See also

See section “13. Examples” [RFC7159]:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
   "Image": {
      "Width": 800,
      "Height": 600,
      "Title": "View from 15th Floor",
      "Thumbnail": {
         "Url":
         "http://www.example.com/image/481989943",
         "Height": 125,
         "Width": 100
      },
      "Animated" : false,
      "IDs": [116, 943, 234, 38793]
   }
}

The application with JSONData and JSONPointer, which e.g. sets the flag ‘/Image/Animated’ to ‘true’ / True.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
D = JSONData(
        {
           "Image": {
              "Width": 800,
              "Height": 600,
              "Title": "View from 15th Floor",
              "Thumbnail": {
                 "Url": "http://www.example.com/image/481989943",
                 "Height": 125,
                 "Width": 100
              },
              "Animated" : False, # false,
              "IDs": [116, 943, 234, 38793]
           }
        }
    )


# does not verify childnode, when 'parent=True' <=> 'new' does no longer exist
targetnode = JSONPointer('/Image/Animated')

# new item
sourcenode = True

# replace old by new item
ret = D.branch_replace(sourcenode, targetnode)
assert ret == True

# verify new item
x = D('/Image/Animated')  # see JSONData.__call__
assert x == True

print(D)  # print uses JSON decoder, thus 'True' => 'true'

Results in:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
{
    "Image": {
        "Width": 800,
        "Height": 600,
        "Title": "View from 15th Floor",
        "Thumbnail": {
            "Url": "http://www.example.com/image/481989943",
            "Height": 125,
            "Width": 100
        },
        "Animated": true,
        "IDs": [
            116,
            943,
            234,
            38793
        ]
    }
}

The JSON keyword ‘true’ is correctly transformed from the Python representation True by the print method, same for the import/export parsers.

Create Arrays

See also

See section “13. Examples” [RFC7159]:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
[
   {
      "precision": "zip",
      "Latitude": 37.7668,
      "Longitude": -122.3959,
      "Address": "",
      "City": "SAN FRANCISCO",
      "State": "CA",
      "Zip": "94107",
      "Country": "US"
   },
   {
      "precision": "zip",
      "Latitude": 37.371991,
      "Longitude": -122.026020,
      "Address": "",
      "City": "SUNNYVALE",
      "State": "CA",
      "Zip": "94085",
      "Country": "US"
   }
]

The application with JSONData and JSONPointer, which e.g. sets the flag ‘/Image/Animated’ to ‘true’ / True.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
D = JSONData(
        [
           {
              "precision": "zip",
              "Latitude": 37.7668,
              "Longitude": -122.3959,
              "Address": "",
              "City": "SAN FRANCISCO",
              "State": "CA",
              "Zip": "94107",
              "Country": "US"
           },
           {
              "precision": "zip",
              "Latitude": 37.371991,
              "Longitude": -122.026020,
              "Address": "",
              "City": "SUNNYVALE",
              "State": "CA",
              "Zip": "94085",
              "Country": "US"
           }
        ]
    )

# modify
targetnode = JSONPointer('/0/Address')
sourcenode = "office"
ret = D.branch_replace(sourcenode, targetnode)
assert ret == True

targetnode = JSONPointer('/1/Address')
sourcenode = "soho"
ret = D.branch_replace(sourcenode, targetnode)
assert ret == True

# verify
x = D('/0/Address')  # see JSONData.__call__
assert x == "office"

x = D('/1/Address')  # see JSONData.__call__
assert x == "soho"

print(D)  # print uses JSON decoder, thus 'True' => 'true'

Results in:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
[
    {
        "precision": "zip",
        "Latitude": 37.7668,
        "Longitude": -122.3959,
        "Address": "office",
        "City": "SAN FRANCISCO",
        "State": "CA",
        "Zip": "94107",
        "Country": "US"
    },
    {
        "precision": "zip",
        "Latitude": 37.371991,
        "Longitude": -122.02602,
        "Address": "soho",
        "City": "SUNNYVALE",
        "State": "CA",
        "Zip": "94085",
        "Country": "US"
    }
]

JSON Schema Validation

JSONData()

The schema validation is an optional part of the class JSONData.

The JSON data

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
  "address":{
    "streetAddress": "21 2nd Street",
    "city":"New York",
    "houseNumber":12
  },
  "phoneNumber":
    [
    {
      "type":"home",
      "number":"212 555-1234"
    },
    {
      "type":"office",
      "number":"313 444-555"
    },
    {
      "type":"mobile",
      "number":"777 666-555"
    }
  ]
}

is validated by the JSON schema

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
{
   "$schema": "http://json-schema.org/draft-03/schema",
   "_comment": "This is a comment to be dropped by the initial scan:object(0)",
   "_doc": "This is a doc string to be inserted when the language supports it.:object(0)",
   "_doc": "Concatenated for the same instance.:object(0)",
   "type":"object",
   "required":false,
   "properties":{
      "address": {
         "_comment": "This is a comment(0):address",
         "type":"object",
         "required":true,
         "properties":{
            "city": {
               "type":"string",
               "required":true
            },
            "houseNumber": {
               "type":"number",
               "required":false
            },
            "streetAddress": {
               "type":"string",
               "required":true
            }
         }
      },
      "phoneNumber": {
         "_comment": "This is a comment(1):array",
         "type":"array",
         "required":false,
         "items":
         {
            "type":"object",
            "required":false,
            "properties":{
               "number": {
                  "type":"string",
                  "required":false
               },
               "type": {
                  "type":"string",
                  "required":false
               }
            }
         }
      }
   }
}

The processing code is:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# -*- coding:utf-8   -*-

from __future__ import absolute_import
from __future__ import print_function

import unittest
import os
import sys

import json
import jsonschema

# import 'jsondata'
from jsondata.jsondataserializer import JSONDataSerializer as ConfigData
from jsondata  import MS_DRAFT4
from jsondata import JSONDataKeyError, JSONDataNodeTypeError

# name of application, used for several filenames as MS_DRAFT4
_APPNAME = "jsondc"
appname = _APPNAME


datafile = os.path.abspath(os.path.dirname(__file__)) \
    + os.sep + str('datafile.json')
schemafile = os.path.abspath(os.path.dirname(__file__)) \
    + os.sep + str('schema.jsd')

kargs = {}
kargs['datafile'] = datafile
kargs['schemafile'] = schemafile
kargs['nodefaultpath'] = True
kargs['nosubdata'] = True
kargs['pathlist'] = os.path.dirname(__file__)
kargs['validator'] = MS_DRAFT4

configdata = ConfigData(appname, **kargs)

resx = {'address': {'streetAddress': '21 2nd Street', 'city': 'New York', 'houseNumber': 12},
        'phoneNumber': [{'type': 'home', 'number': '212 555-1234'},
                        {'type': 'office', 'number': '313 444-555'},
                        {'type': 'mobile', 'number': '777 666-555'}]}

assert configdata.data == resx
pass

JSONData.validate()

Conversions

json to jsondata

The package jsondata relies on the standard package json or ujson, therefore the conversion requires a call only. The data is not actually converted, but just included by refrence into a control, administration, and arithmetic branch operations object. The data is still accessible native by the stored reference JSONData.data.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
jdata = { 'a': { 'b': { 'c': 2, 'd': 3 } } }

jsondata = JSONData(jdata)

print()
print(jsondata)
print()

Results in:

1
2
3
4
5
6
7
8
{
    "a": {
        "b": {
            "c": 2,
            "d": 3
        }
    }
}

Pointer from Node

The JSONPointer for a provided python reference to a node within a JSON data tree.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
jdata = { 'a': { 'b': { 'c': 2, 'd': 3 } } }

targetnode = jdata['a']['b']['c']
jsondata = JSONData(jdata)

path_list = fetch_pointerpath(targetnode, jdata)
path = JSONPointer(path_list[0])

print()
print(str(path_list) + ' -> ["' + str(path) + '"]')
print()

Results in:

1
[['a', 'b', 'c']] -> ["/a/b/c"]

Node from Pointer

The JSONPointer for a provided python reference to a node within a JSON data tree.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
jdata = { 'a': { 'b': { 'c': 2, 'd': 3 } } }

targetpointer = '/a/b/c'

jsonpointer = JSONPointer(targetpointer)
jsondata = JSONData(jdata)

targetnode = jsonpointer(jsondata)

r = repr(jsonpointer)
s = str(jsonpointer)

print()
print('"' + str(jsonpointer) + '" -> ' + str(targetnode))
print()

Results in:

1
"/a/b/c" -> 2

The same for a list with index ‘2’.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
jdata = { 'a': { 'b': { 'c': [1, 2, 3], 'd': 3 } } }

targetpointer = '/a/b/c/2'

jsonpointer = JSONPointer(targetpointer)
jsondata = JSONData(jdata)

targetnode = jsonpointer(jsondata)

print()
print('"' + str(jsonpointer) + '" -> ' + str(targetnode))
print()

Results in:

1
"/a/b/c/-" -> 3

The same for a list with special index ‘-‘ [RFC6901].

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
jdata = { 'a': { 'b': { 'c': [1, 2, 3], 'd': 3 } } }

targetpointer = '/a/b/c/-'

jsonpointer = JSONPointer(targetpointer)
jsondata = JSONData(jdata)

targetnode = jsonpointer(jsondata)

print()
print('"' + str(jsonpointer) + '" -> ' + str(targetnode))
print()

Results in:

1
"/a/b/c/-" -> 3

Parent Node from Pointer

The JSONPointer for the parent of a provided python pointer.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
jdata = { 'a': { 'b': { 'c': [1, 2, 3], 'd': 3 } } }

targetpointer = '/a/b/c/2'

jsonpointer = JSONPointer(targetpointer)
jsondata = JSONData(jdata)

parent, child = jsonpointer.get_node_and_child(jsondata)

print()
print('"' + str(jsonpointer) + '" -> parent-node = ' + str(parent) + ' child-node = ' + str(child))

parent_pointer = fetch_pointerpath(parent, jsondata)[0]
child_pointer = fetch_pointerpath(child, jsondata)[0]
print('"' + str(jsonpointer)
      + '" -> parent-pointer = ' + str(JSONPointer(parent_pointer))
      + ' child-pointer = ' + str(JSONPointer(child_pointer)))
print()

Results in:

1
2
"/a/b/c/2" -> parent-node = [1, 2, 3] child-node = 3
"/a/b/c/2" -> parent-pointer = /a/b/c child-pointer = /a/b/c/2

Parent Node for Node

The parent node for a provided node.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

# JSON document
jdata = { 'a': { 'b': { 'c': [1, 2, 3], 'd': 3 } } }


jsondata = JSONData(jdata)
jsonnode = jsondata['a']['b']['c'][2]  #pylint: disable=unsubscriptable-object

node_path = fetch_pointerpath(jsonnode, jsondata)[0]
jsonpointer = JSONPointer(node_path)

parent, child = jsonpointer.get_node_and_child(jsondata)


print()
print('jsondata = ' + str(jsondata))
print('json-node = ' + str(jsonnode))
print()
print(' -> parent-json-node = ' + str(parent))

parent_pointer = fetch_pointerpath(parent, jsondata)[0]
child_pointer = fetch_pointerpath(child, jsondata)[0]
print(' -> parent-pointer = ' + str(JSONPointer(parent_pointer)))
print(' -> child-pointer = ' + str(JSONPointer(child_pointer)))
print()

Results in:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
jsondata = {
    "a": {
        "b": {
            "c": [
                1,
                2,
                3
            ],
            "d": 3
        }
    }
}
json-node = 3

 -> parent-json-node = [1, 2, 3]
 -> parent-pointer = /a/b/c
 -> child-pointer = /a/b/c/2

Comparison Operators

S == x

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

S = JSONData(
        { 'a': { 'b': { 'c': 2, 'd': 3 } } }
    )

x = JSONData(
        { 'a': { 'b': { 'c': 2, 'd': 3 } } }
    )

assert S == x
assert S.data == x.data

print(S == X)
print(S.data == x.data)

S != x

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# -*- coding:utf-8   -*-
from __future__ import absolute_import
from __future__ import print_function

from jsondata.jsondata import JSONData
from jsondata.jsonpointer import JSONPointer

S = JSONData(
        { 'a': { 'b': { 'c': 2, 'd': 3 } } }
    )

x = JSONData(
        { 'a': { 'b': { 'c': 2, 'd': 4 } } }
    )

assert S != x
assert S.data != x.data

print(S != x)
print(S.data != x.data)