简体   繁体   中英

Update a dictionary value using python

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'}}]]

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 (ie '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"
          }
        }
      ]
    }
      ]
    }
  ]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM