0

I have a json file, which when loaded in python using json.loads() becomes a dictionary. The json data is a nested dictionary which can contain a 'groups' key inside another 'groups' key. The values inside the 'groups' key are a 'name' key and a 'properties' key.

Each 'properties' key has a unique 'name' and a 'value' key.

My objective is to search for a 'groups' key having its 'name' key value as "SportCar", which has a properties key having a name key value as "BMW", and only when these conditions are satisfied, update the 'data' key from 'data':value1 to 'data':value2.

An example of the json is as follows

{
  "groups": [
    {
      "name": "SportCar",
      "properties": [
        {
          "name": "BMW",
          "value": {
            "type": "String",
            "encoding": "utf-8",
            "data": "value1"
          }
        },
        {
          "name": "Audi",
          "value": {
            "type": "Boolean",
            "data": true
          }
        }
      ],
      "groups": [
        {
          "name": "Trucks",
          "properties": [
            {
              "name": "Volvo",
              "value": {
                "type": "String",
                "encoding": "utf-8",
                "data": "value1"
              }
            }
          ]
        }
      ]
    },
    {
      "name": "MotorCycle",
      "properties": [
        {
          "name": "Yamaha",
          "value": {
            "type": "String",
            "encoding": "utf-8",
            "data": "value1"
          }
        }
      ],
      "groups": [
        {
          "name": "Speeders",
          "properties": [
            {
              "name": "prop2",
              "value": {
                "type": "String",
                "encoding": "utf-8",
                "data": "value1"
              }
            }
          ]
        }
      ]
    }
  ]
}

The above json is contained in myjson22.json. Here is what I have tried so far:

import json
from pprint import pprint

json_data=open('myjson22.json', 'r')
data = json.load(json_data)
#print(data)

def get_recursively(search_dict, field):
    """
    To read the json data as type dict and search all 'groups' keys for the 'name' key value value provided.
    """
    fields_found = []

    for key, value in search_dict.items():

        if key == field:
            fields_found.append(value)

        elif isinstance(value, dict):
            results = get_recursively(value, field)
            for result in results:
                fields_found.append(result)

        elif isinstance(value, list):
            for item in value:
                if isinstance(item, dict):
                    more_results = get_recursively(item, field)
                    for another_result in more_results:
                        fields_found.append(another_result)

    return fields_found
get_recursively(data, ["properties"][0])

and the output was:

 [[{'name': 'BMW',
   'value': {'data': 'value1', 'encoding': 'utf-8', 'type': 'String'}},
  {'name': 'Audi', 'value': {'data': True, 'type': 'Boolean'}}],
 [{'name': 'Volvo',
   'value': {'data': 'value1', 'encoding': 'utf-8', 'type': 'String'}}],
 [{'name': 'Yamaha',
   'value': {'data': 'value1', 'encoding': 'utf-8', 'type': 'String'}}],
 [{'name': 'prop2',
   'value': {'data': 'value1', 'encoding': 'utf-8', 'type': 'String'}}]]
3
  • 5
    What have you tried so far and why did it fail to achieve the results you wanted? Commented Aug 8, 2016 at 19:58
  • 1
    ONE property but properties is an array? Commented Aug 8, 2016 at 20:00
  • Please share the code and error if any. Commented Aug 8, 2016 at 20:06

1 Answer 1

2

A way to implement this recursive solution is with backtracking. When no more 'groups' keys are are found nested inside the root key, the 'name' key value is matched with groups_name parameter, which is 'SportCar' in our case. If this condition is satisfied check for the values inside same 'groups' key's (i.e. 'SportCar' key's) 'properties' key and match its 'name' key value with the properties_name parameter (which is 'BMW' in our case). If this second condition is also true, then update the 'data' key value inside the same 'properties' key, as per requirements, or else return (for backtracking).

import json

json_data = open('myjson22.json', 'r')

data = json.load(json_data)

def get_recursively( myJson, groups_name, properties_name, value2):

    if 'groups' in myJson.keys():
        # As there are multiple values inside 'groups' key
        for jsonInsideGroupsKey in myJson['groups']:  
            get_recursively( jsonInsideGroupsKey, groups_name, properties_name, value2)

    if 'name' in myJson.keys():
        # check for groups name
        if myJson['name'] == groups_name:
            # check for properties name
            if myJson['properties'][0]['name'] == properties_name:
                # Update value. The changes will persist as we backtrack because
                # we are making the update at the original memory location
                # and not on a copy. For more info see deep and shallow copy.
                myJson['properties'][0]['value']['data'] = value2
    return

get_recursively(data,'SportCar','BMW','changedValue1')
get_recursively(data,'Speeders','prop2','changedValue2')
print data

my output:

{u'groups': [{u'name': u'SportCar', u'groups': [{u'name': u'Trucks', u'properties': [{u'name': u'Volvo', u'value': {u'data': u'value1', u'type': u'String', u'encoding': u'utf-8'}}]}], u'properties': [{u'name': u'BMW', u'value': {u'data': 'changedValue1', u'type': u'String', u'encoding': u'utf-8'}}, {u'name': u'Audi', u'value': {u'data': True, u'type': u'Boolean'}}]}, {u'name': u'MotorCycle', u'groups': [{u'name': u'Speeders', u'properties': [{u'name': u'prop2', u'value': {u'data': 'changedValue2', u'type': u'String', u'encoding': u'utf-8'}}]}], u'properties': [{u'name': u'Yamaha', u'value': {u'data': u'value1', u'type': u'String', u'encoding': u'utf-8'}}]}]}

prettified it will look as:

{
  "groups": [
    {
      "name": "SportCar",
      "properties": [
    {
      "name": "BMW",
      "value": {
        "type": "String",
        "encoding": "utf-8",
        "data": "ChangedValue1"
      }
    },
    {
      "name": "Audi",
      "value": {
        "type": "Boolean",
        "data": true
      }
    }
      ],
      "groups": [
    {
      "name": "Trucks",
      "properties": [
        {
          "name": "Volvo",
          "value": {
            "type": "String",
            "encoding": "utf-8",
            "data": "value1"
          }
        }
      ]
    }
      ]
    },
    {
      "name": "MotorCycle",
      "properties": [
    {
      "name": "Yamaha",
      "value": {
        "type": "String",
        "encoding": "utf-8",
        "data": "value1"
      }
    }
      ],
      "groups": [
    {
      "name": "Speeders",
      "properties": [
        {
          "name": "prop2",
          "value": {
            "type": "String",
            "encoding": "utf-8",
            "data": "ChangedValue2"
          }
        }
      ]
    }
      ]
    }
  ]
}
Sign up to request clarification or add additional context in comments.

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.