Seth Killian Seth Killian - 6 months ago 40
JSON Question

Mapping to specific object with json

I've seen posts on here with loading a json file and mapping it to an arbitrary object without predetermined attributes, but I'd like to map to an existing object so when I create new objects, they're like types, and if I want to add methods for that object later, it's not a problem. I tried adding **kwargs to the parameters, but that doesn't seem to work as I end up with:

TypeError: __init__() takes 1 positional argument but 2 were given


Here's the class and the load method:

import json

user_library = []

class Term(object):

def __init__(self, **kwargs):
self.term = None
self.type = None
self.translation = None
self.learned = None
self.diffculty = None
self.streak = None
self.totalCorrect = None
self.totalAttempts = None
self.lastViewed = None
for key in kwargs:
setattr(self, key, kwargs[key])


def load(file='data/user_library.json'):
with open(file) as data_file:
data_loaded = json.load(data_file)
for term in data_loaded:
user_library.append(Term(term))


Here's an example of what I'm trying to pass to the constructor:

{'diffculty': None, 'translation': 'to have', 'totalCorrect': None, 'learned': False, 'term': 'avoir', 'streak': None, 'type': 'verb', 'totalAttempts': None, 'lastViewed': 1502899731.261366}

Answer Source

So, a couple of things, first you want to allow for both positional and keyword arguments in your class:

class Term():

    def __init__(self, *args, **kwargs):

That is what is causing the error, is that you are trying to pass term as a positional argument to the constructor, but the constructor does not allow for this.

Second, you can pass your kwarg dictionary in like this:

Term(**data_loaded)

This will pass your full dictionary as kwargs to __init__. In other words, no need for the loop.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download