0

Currently I am converting a json to a Python object using the namedtuple class. This way I can easily select data for e.g. print(json.some_json_variable). However, my Json contains the following key: "@odata.context" and this ofcourse, cannot be used as a variable name because it contains a "@" and a ".".

At the moment I am using the json.load(json) function to load the json. Then I rename the "@odata.context" key, to "odataContext" so that it no longer contains a "@" and a ".". Next, I convert the json to a string using json.dumps(json) and after that, I convert it to an object using the json.loads(json) function. As you can understand, this method is not really efficient.

def load_json(input_json):
    with open(input_json, 'r') as l_json:
        data = json.load(l_json)
        data["odataContext"] = data.pop("@odata.context")
        data = json.dumps(data)
        data = json.loads(data, object_hook=lambda d: namedtuple('data', d.keys())(*d.values()))

Is there any way this can be done more efficiently? I think that using up to 2 functions can be easily achievable, but I do not know how.

Marc Dirven
  • 309
  • 2
  • 18

2 Answers2

1

You can replace the unwanted characters in the object_hook= parameter lambda:

json_data = '''{
    "@odata.context": 1,
    "variable": "Hello"
}'''

import json
from collections import namedtuple

def load_json(input_json):
    data = json.loads(input_json, object_hook=lambda d: namedtuple('data', (k.replace('@', '').replace('.', '_') for k in d.keys()) )(*d.values()))
    return data

data = load_json(json_data)
print(data.odata_context)
print(data.variable)

Prints:

1
Hello
Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91
0

I think the easiest approach would be to replace "@odata.context" with "odataContext" before loading it into JSON. Try something like:

def load_json(input_json):
    with open(input_json, 'r') as l_json:
        data = l_json.read().replace("@odata.context", "odataContext")
        data = json.loads(data, object_hook=lambda d: namedtuple('data', d.keys())(*d.values()))
tituszban
  • 4,797
  • 2
  • 19
  • 30