Shrikant
Shrikant

Reputation: 803

Update JSON value for a particular key, preserving JSON structure

I need to update the value for key (id) in the JSON file. Value is stored in the variable ids. I am able to update the key id with ids (updated value), but the structure of the JSON file gets messed up. Can anyone suggest me a way to doing it without messing up the JSON structure?

Code:

ids=10
filename='update_test.json'
with open(filename,'r') as f:
    data=json.load(f)
    data['id'] = ids
os.remove(filename)
with open(filename,'w') as f:
    json.dump(data,f,indent=4)

Input JSON:

{
    "accountableExecutiveTech": "string",
    "api": true,
    "arrivalFrequency": "string",
    "bucketName": "string",
    "businessDataset": "string",
    "columns": [{
        "businessColumnName": "string",
        "childColumns": [{}],
        "columnOrder": 0,
        "description": "string",
        "descriptiveName": "string",
        "format": "string",
        "hierarchicalName": "string",
        "id": 0,
        "isArray": true,
        "length": 0,
        "name": "string",
        "parentColumnName": "string",
        "partitionColumn": true,
        "technicalDatasetId": 0,
        "technicalDatasetName": "string",
        "technicalNamespace": "string",
        "technicalPlatformName": "string",
        "type": "string",
        "validValues": {}
    }],
    "controlMJobName": "string",
    "credit": true,
    "delimiter": "string",
    "delimiterFlag": true,
    "description": "string",
    "dqPrioritized": true,
    "fileFormat": "string",
    "id": "",
    "name": "string",
    "namespace": "string",
    "npi": true,
    "objectKey": "string",
    "pci": true,
    "performingDataSteward": "string",
    "platformName": "string",
    "retentionPlan": "string",
    "selectAdGroup": "string",
    "sourceDatasets": [{
        "id": 4534,
        "name": "string",
        "namespace": "string",
        "platformName": "string"
    }],
    "tags": ["string"]
}

Output JSON:

{
    "accountableExecutiveTech": "string",
    "delimiterFlag": true,
    "performingDataSteward": "string",
    "api": true,
    "dqPrioritized": true,
    "id": 14044,
    "namespace": "string",
    "fileFormat": "string",
    "selectAdGroup": "string",
    "pci": true,
    "platformName": "string",
    "columns": [
        {
            "isArray": true,
            "partitionColumn": true,
            "description": "string",
            "technicalDatasetId": 0,
            "format": "string",
            "technicalPlatformName": "string",
            "parentColumnName": "string",
            "columnOrder": 0,
            "length": 0,
            "childColumns": [
                {}
            ],
            "descriptiveName": "string",
            "validValues": {},
            "technicalDatasetName": "string",
            "technicalNamespace": "string",
            "hierarchicalName": "string",
            "businessColumnName": "string",
            "type": "string",
            "id": 0,
            "name": "string"
        }
    ],
    "businessDataset": "string",
    "npi": true,
    "description": "string",
    "tags": [
        "string"
    ],
    "arrivalFrequency": "string",
    "objectKey": "string",
    "bucketName": "string",
    "controlMJobName": "string",
    "name": "string",
    "retentionPlan": "string",
    "credit": true,
    "delimiter": "string",
    "sourceDatasets": [
        {
            "platformName": "string",
            "namespace": "string",
            "id": 4534,
            "name": "string"
        }
    ]

Upvotes: 1

Views: 3125

Answers (1)

randomir
randomir

Reputation: 18697

I'm guessing you're referring to the order of keys in you dictionary (later in serialized JSON) that gets changed. That's because by default json.load() uses dict as an underlaying mapping type.

But you can change that to a dictionary type that preserves order, called collections.OrderedDict:

from collections import OrderedDict

ids = 10
filename = 'update_test.json'

with open(filename, 'r') as f:
    data = json.load(f, object_pairs_hook=OrderedDict)
    data['id'] = ids

with open(filename, 'w') as f:
    json.dump(data, f, indent=4)

Note the use of object_pairs_hook=OrderedDict in json.load(). From the docs:

object_pairs_hook is an optional function that will be called with the result of any object literal decoded with an ordered list of pairs. The return value of object_pairs_hook will be used instead of the dict. This feature can be used to implement custom decoders that rely on the order that the key and value pairs are decoded (for example, collections.OrderedDict() will remember the order of insertion).

Upvotes: 3

Related Questions