5

Trying to find the easiest way to sort nested json data. Everything I've tried up to this point seems to fail. I'm using Python 2.7 and attempting to sort by name attribute. Here's one of the many python samples I tried:

    def sort_json(self,json_data):
        data_obj = json.dumps(json_data,sort_keys=True)
        return sorted(data_obj["data"]["workflows"]["allWorkflows"], 
        key=lambda d: d["name"])

Here's a sample of the unsorted json:

{
  "data": {
    "workflows": {
      "allWorkflows": [{
        "name": "ICX-SLX Config Basic Support",
        "version": 106,
        "path": "/Workflows/System/Config/Basic Support/ICX-SLX Config Basic Support"
      }, {
        "name": "ICX Upgrade Firmware",
        "version": 37,
        "path": "/Workflows/System/Inventory/Upgrade/ICX Upgrade Firmware"
      }, {
        "name": "Quarantine_PCAP_Flow",
        "version": 357,
        "path": "/Workflows/System/Security/Quarantine_PCAP_Flow"
      }, {
        "name": "ICX-MLX Backup Configuration",
        "version": 101,
        "path": "/Workflows/System/Inventory/Backup/ICX-MLX Backup Configuration"
      }, {
        "name": "ICX-SLX-MLX Restart Device",
        "version": 15,
        "path": "/Workflows/System/Inventory/Restart/ICX-SLX-MLX Restart Device"
      }, {
        "name": "Revert_Quarantine_End_System",
        "version": 169,
        "path": "/Workflows/System/Security/Revert_Quarantine_End_System"
      }]
    }
  }
}

Any working examples would be really appreciated.

2
  • What is the problem? Commented Dec 3, 2018 at 18:55
  • For the above code example I get the following error: TypeError: string indices must be integers, not str Commented Dec 3, 2018 at 19:15

3 Answers 3

4

If I understood correctly you need to remove the line:

data_obj = json.dumps(json_data,sort_keys=True) 

for example:

def sort_json(json_data):
    workflows = json_data["data"]["workflows"]["allWorkflows"]
    return sorted(workflows, key=lambda d: d["name"])


jd = {
    "data": {
        "workflows": {
            "allWorkflows": [{
                "name": "ICX-SLX Config Basic Support",
                "version": 106,
                "path": "/Workflows/System/Config/Basic Support/ICX-SLX Config Basic Support"
            }, {
                "name": "ICX Upgrade Firmware",
                "version": 37,
                "path": "/Workflows/System/Inventory/Upgrade/ICX Upgrade Firmware"
            }, {
                "name": "Quarantine_PCAP_Flow",
                "version": 357,
                "path": "/Workflows/System/Security/Quarantine_PCAP_Flow"
            }, {
                "name": "ICX-MLX Backup Configuration",
                "version": 101,
                "path": "/Workflows/System/Inventory/Backup/ICX-MLX Backup Configuration"
            }, {
                "name": "ICX-SLX-MLX Restart Device",
                "version": 15,
                "path": "/Workflows/System/Inventory/Restart/ICX-SLX-MLX Restart Device"
            }, {
                "name": "Revert_Quarantine_End_System",
                "version": 169,
                "path": "/Workflows/System/Security/Revert_Quarantine_End_System"
            }]
        }
    }
}

result = sort_json(jd)
print(result)

Output

[{'version': 37, 'name': 'ICX Upgrade Firmware', 'path': '/Workflows/System/Inventory/Upgrade/ICX Upgrade Firmware'}, {'version': 101, 'name': 'ICX-MLX Backup Configuration', 'path': '/Workflows/System/Inventory/Backup/ICX-MLX Backup Configuration'}, {'version': 106, 'name': 'ICX-SLX Config Basic Support', 'path': '/Workflows/System/Config/Basic Support/ICX-SLX Config Basic Support'}, {'version': 15, 'name': 'ICX-SLX-MLX Restart Device', 'path': '/Workflows/System/Inventory/Restart/ICX-SLX-MLX Restart Device'}, {'version': 357, 'name': 'Quarantine_PCAP_Flow', 'path': '/Workflows/System/Security/Quarantine_PCAP_Flow'}, {'version': 169, 'name': 'Revert_Quarantine_End_System', 'path': '/Workflows/System/Security/Revert_Quarantine_End_System'}]
Sign up to request clarification or add additional context in comments.

6 Comments

Tried your example and get back this error: workflows = json_data["data"]["workflows"]["allWorkflows"] TypeError: string indices must be integers, not str
What are you passing to the function a string or a dictionary?
Passing it in as a string
Pass it as a dictionary, do not transform the dictionary into a string
There we go... Used json.loads(json_data) and that worked. Thanks... Is there anyway to convert the output to the original layout versus 1 line?
|
0

Hi Bill: I think the complication comes from the triple nesting of the json file. Once I removed the overhead layers and made a new dictionary of {name: version, path} then I can sort: (This might be a little more cumbersome than you want, but at least it made the problem clear to me. Hope this helps!)

import json

with open("sample.json") as json_data:
    d = json.load(json_data)

key = 'data'
key2 = 'workflows'
key3 = 'allWorkflows'

list1 = []
list2 = []
list3 = []

for k in d[key][key2][key3]:
    name_d = k
    list1.append(name_d['name'])
    list2.append(name_d['version'])
    list3.append(name_d['path'])

mydict = {i:[j, k] for i, j, k in zip(list1, list2, list3)}
print(sorted(mydict.items()))

Comments

0

You could use a (partially complete) recursive solution to handle more levels / nesting:

input.json

{"foo": {"bar": [3,2,1], "bax": {"buz": [6,5,4]}}, "too": [9,8,7], "farm": [{"boo": [7,6]}, {"coo": ["def", "abc"]}, {"loo": {"dog": [6,9,1], "cat": [{"fog": [3,2,1]}]}}]}

expected.json

{"foo": {"bar": [1,2,3], "bax": {"buz": [4,5,6]}}, "too": [7,8,9], "farm": [{"boo": [6,7]}, {"coo": ["abc", "def"]}, {"loo": {"dog": [1,6,9], "cat": [{"fog": [1,2,3]}]}}]}

function

def sort_json(payload: Dict) -> Dict:
  for k, v in payload.items():
    if isinstance(v, dict):
      sort_json(v)
    else:
      if all(isinstance(x, int) or isinstance(x, str) for x in v):
        v.sort()
      if all(isinstance(x, dict) or isinstance(x, dict) for x in v):
        for j in v:
          sort_json(j)
  return payload

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.