3

Is it possible to use json.loads() in python to create an actual Python object instead of a dict value?

I would rather not have to do json_data['value_name'] and just to json_object.my_value.

Adam Haile
  • 30,705
  • 58
  • 191
  • 286
  • Do you have an actual use case for this? Currently your question just reads like "I prefer looking at attribute accesses instead of dict lookups" - in this case the answer would be, just use the dictionary. If you do have a use case, the answer might depend on it; but a quick and simple solution to this can be trivially done with `setattr`... – l4mpi Oct 19 '13 at 21:33

1 Answers1

-1

You can use Python alternative syntax for creating types:

attributes = {
    'a': 12,
    'b': 'there-is-a-value-here',
    'greet': (lambda self: print("Hi, my a is {}".format(self.a)))
}
SomeCoolType = type("SomeCoolType", (), attributes)
someCoolInstance = SomeCoolType()
someCoolInstance.greet() # this prints "Hi, my a is 12"

The first argument is type name, second is tuple with parent classes, and the third is attributes dictionary. So, having that in mind, you can first decode JSON to dict, then construct a type from it, and then instantiate it:

d = json.loads(json_data)
T = type("JSON", (), d)
json_object = T()

Or, shorter:

json_object = type("JSON", (), json.loads(json_data))()

This simple approach will only change top-level dictionary to object; if you want to be able to call json_object.param.something.value, you have to convert it via recursion (similar to shallow vs. deep copy):

def to_object(dictionary):
    for key, value in dictionary.items():
        if isinstance(value, dict): dictionary[key] = value
    return type("JSON", (), dictionary)

json_object = to_object(json.loads(json_data))
Wojciech Ptak
  • 683
  • 4
  • 14
  • 3
    Downvoted - you're creating new classes on the fly and abuse class attributes for storing the data (that's bad as you're #1 creating one class per JSON object, and #2 lose time on every attribute lookup as it's not an instance attribute; furthermore this will break rather badly if the json data contains keys like `"__init__"` or `"__new__"`). A much better and simpler way would be using a class that takes the dict in its `__init__` and either uses `setattr` to create instance attributes, or just stores the dict and overrides `__getattr__` to access it. – l4mpi Oct 19 '13 at 21:44