PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Sunday, July 24, 2022

[FIXED] How to code a json tree pruning in Python3?

 July 24, 2022     json, python-3.x, tree     No comments   

Issue

The structure of json tree is known. However, how do we prune the json tree in Python3?

I had been trying to create a medical file format for patients. Each json object is a case or detail about a patient.

I tried linearizing the json, and count the levels, but the code quickly gets untenable. I also looked at binary trees, but this is not a binary tree. I attempted to itemized each json object as an atom, which means it would be a form of pointer, however, python does not have pointers.

Examples:

  1. insert / replace json into 0.1.2
  2. delete json at 0.1.1.3
  3. extract json at 0.1.1.1 // may be sub-tree
{ // 0
    "field1": "value1",
    "field2": { // 0.0
        "field3": "val3",
        "field4": "val4"
    }
}

For example, I want to remove 0.0:

{ // 0
    "field1": "value1",
// removed
}

to insert 0.1:

{ // 0
    "field1": "value1",
    "field2": { // 0.0
        "field3": "val3",
        "field4": "val4"
    }

    "field2x": { // 0.1
        "field3x": "val3x",
        "field4x": "val4x"
    }

}

0.1 must be given:


    "field2x": { // 0.1
        "field3x": "val3x",
        "field4x": "val4x"
    }

now i want to insert 0.1.0:


    "field2xx": { // 0.1.0
        "field3xx": "val3xx",
        "field4xx": "val4xx"
    }
{ // 0
    "field1": "value1",
    "field2": { // 0.0
        "field3": "val3",
        "field4": "val4"
    }

    "field2x": { // 0.1
        "field3x": "val3x",
        "field4x": "val4x"

         "field2xx": { // 0.1.0
             "field3xx": "val3xx",
             "field4xx": "val4xx"
         }
    }

}

now I want to extract 0.1, it should give me:


    "field2x": { // 0.1
        "field3x": "val3x",
        "field4x": "val4x"

         "field2xx": { // 0.1.0
             "field3xx": "val3xx",
             "field4xx": "val4xx"
         }
    }

leaving:


{ // 0
    "field1": "value1",
    "field2": { // 0.0
        "field3": "val3",
        "field4": "val4"
    }

// removed 0.1

}

Solution

I second the people saying that indexing a dictionary by position is not the natural way, but it is possible since python3.7 as the dict is insertion-ordered as a guaranteed language-feature in python.

This is my working example, the indices are different than your schematic, but it made more sense for me to index it like that. It makes use of recursive traversing of the data by the given indices and then depending on the operation removing, inserting or returning the nested data.

The insertion of data makes use of the mentioned ordering by insertion in python. data.update(dict(**insert, **after))

  • It leaves the data before the insertion as is (so it is older and thus staying in front)
  • Then it updates the inserted data
  • And last the data after the inserted data (making it the oldest and thus at the back).
from copy import deepcopy
import itertools
import json


def traverse(data, index_list):
    index = index_list.pop()
    if index_list:
        nested_data = list(data.values())[index]
        return traverse(nested_data, index_list)
    return data, index


def insert(data, data_insert, index_list):
    data, index = traverse(data, index_list)
    after = dict(itertools.islice(data.items(), index)) or None
    data.update(dict(**data_insert, **after))


def remove(data, index_list):
    key, data = get(data, index_list)
    return {key: data.pop(key)}


def get(data, index_list):
    data, index = traverse(data, index_list)
    key = list(data.keys())[index]
    return key, data


def run_example(example_name, json_in, index_str, operation, data_insert=None):
    print("-" * 40 + f"\n{example_name}")

    print(f"json before {operation} at {index_str}:")
    print(json.dumps(json_in, indent=2, sort_keys=False))

    index_list = [int(idx_char) for idx_char in index_str.split(".")]
    if operation == "insert":
        json_out = insert(json_in, data_insert, index_list)
    elif operation == "remove":
        json_out = remove(json_in, index_list)
    elif operation == "get":
        key, data = get(json_in, index_list)
        json_out = {key: data[key]}
    else:
        raise NotImplementedError("Not a valid operation")

    print(f"json after:")
    print(json.dumps(json_in, indent=2, sort_keys=False))

    print(f"json returned:")
    print(json.dumps(json_out, indent=2, sort_keys=False))


json_data = {
    "field1": "value1",
    "field2": {
        "field3": "val3",
        "field4": "val4"
    }
}

run_example("example 1", deepcopy(json_data), "1", "remove")
run_example("example 2", json_data, "2", "insert", {"field2x": {"field3x": "val3x", "field4x": "val4x"}})
run_example("example 3", json_data, "2", "get")
run_example("example 4", json_data, "2.2", "insert", {"field2xx": {"field3xx": "val3xx", "field4xx": "val4xx"}})
run_example("example 5", json_data, "2", "remove")

This gives the following output:

----------------------------------------
example 1
json before remove at 1:
{
  "field1": "value1",
  "field2": {
    "field3": "val3",
    "field4": "val4"
  }
}
json after:
{
  "field1": "value1"
}
json returned:
{
  "field2": {
    "field3": "val3",
    "field4": "val4"
  }
}
----------------------------------------
example 2
json before insert at 2:
{
  "field1": "value1",
  "field2": {
    "field3": "val3",
    "field4": "val4"
  }
}
json after:
{
  "field1": "value1",
  "field2": {
    "field3": "val3",
    "field4": "val4"
  },
  "field2x": {
    "field3x": "val3x",
    "field4x": "val4x"
  }
}
json returned:
null
----------------------------------------
example 3
json before get at 2:
{
  "field1": "value1",
  "field2": {
    "field3": "val3",
    "field4": "val4"
  },
  "field2x": {
    "field3x": "val3x",
    "field4x": "val4x"
  }
}
json after:
{
  "field1": "value1",
  "field2": {
    "field3": "val3",
    "field4": "val4"
  },
  "field2x": {
    "field3x": "val3x",
    "field4x": "val4x"
  }
}
json returned:
{
  "field2x": {
    "field3x": "val3x",
    "field4x": "val4x"
  }
}
----------------------------------------
example 4
json before insert at 2.2:
{
  "field1": "value1",
  "field2": {
    "field3": "val3",
    "field4": "val4"
  },
  "field2x": {
    "field3x": "val3x",
    "field4x": "val4x"
  }
}
json after:
{
  "field1": "value1",
  "field2": {
    "field3": "val3",
    "field4": "val4"
  },
  "field2x": {
    "field3x": "val3x",
    "field4x": "val4x",
    "field2xx": {
      "field3xx": "val3xx",
      "field4xx": "val4xx"
    }
  }
}
json returned:
null
----------------------------------------
example 5
json before remove at 2:
{
  "field1": "value1",
  "field2": {
    "field3": "val3",
    "field4": "val4"
  },
  "field2x": {
    "field3x": "val3x",
    "field4x": "val4x",
    "field2xx": {
      "field3xx": "val3xx",
      "field4xx": "val4xx"
    }
  }
}
json after:
{
  "field1": "value1",
  "field2": {
    "field3": "val3",
    "field4": "val4"
  }
}
json returned:
{
  "field2x": {
    "field3x": "val3x",
    "field4x": "val4x",
    "field2xx": {
      "field3xx": "val3xx",
      "field4xx": "val4xx"
    }
  }
}


Answered By - MangoNrFive
Answer Checked By - Dawn Plyler (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing