Python Forum
Serialization and Deserialization between JSON obj and Python obj
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Serialization and Deserialization between JSON obj and Python obj
#1
Hey guys,
I am currently learning serialization and deserialization between JSON obj and Python obj, there's the sample code:

class Who:

    def __init__(self, name, age):
        self.name = name
        self.age = age


class MyEncoder(json.JSONEncoder):

    def default(self, w):
        if isinstance(w, Who):
            return w.__dict__
        else:
            return super().default(self, z)


class MyDecoder(json.JSONDecoder):

    def __init__(self):
        json.JSONDecoder.__init__(self, object_hook=self.decode_who)

    def decode_who(self, d):
        return Who(**d)


some_man = Who('Jane Doe', 23)
json_str = json.dumps(some_man, cls=MyEncoder)
new_man = json.loads(json_str, cls=MyDecoder)

print(type(new_man))
print(new_man.__dict__)
I understood everything except line 23:
return Who(**d)
specially the double asterisk operator here, I couldn't get the idea of this line will build the python object (type Who)
Could someone help me out?

Thanks!!
Reply
#2
Double asterisk expands a dictionary into keyword arguments.

Who expects to be called with name and age as arguments. It will accept either positional arguments or named arguments. We might have a dictionary with that information:
d = {'name':'myname', 'age':84}
If we try to hand it to Who directly it will interpret it as a single positional argument and ask why you didn't hand in another.

>>> Who(d)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() missing 1 required positional argument: 'age'
If we instead use the ** operator, it will turn it into the keys and values and expand it, basically calling it with the named arguments.

>>> w = Who(**d) # expands to Who(name='myname', age=84)
>>> w.name
'myname'
>>> w.age
84
From python docs
Quote:If the syntax **expression appears in the function call, expression must evaluate to a mapping, the contents of which are treated as additional keyword arguments. If a keyword is already present (as an explicit keyword argument, or from another unpacking), a TypeError exception is raised.
Reply
#3
Thanks for the clear answer and explanation. So after reading it, I understand that:
Who(**d)
is equivalent to do the following:
Who(d['name'],d['age'])
Basically we want to create a Who object using the key of the dictionary.

Is (**d) consider as a more elegant way?
Reply
#4
It's equivalent for that particular dictionary. If there's a case where the dictionary contains additional keys, then you might be handing in elements that the object can't handle.

I don't know that I'd consider it more elegant. It's quite useful when you're passing around parameter lists, especially when you get them passed in other ways (like with function decorators). For the case where you know you need these two parameters, enforcing that with the explicit lookup doesn't seem wrong to me. It also allows the data structure to be extended with other information without requiring your Who object to know about the new keys.

If the datastructure is temporary and created explicitly for handing to Who(), passing it via the ** operation seems okay. If the data structure has any other use, I'd prefer making the call arguments explicit.
Reply
#5
Ok understood! Thanks very much!!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Python Split json into separate json based on node value CzarR 1 6,074 Jul-08-2022, 07:55 PM
Last Post: Larz60+
  difficulties to chage json data structure using json module in python Sibdar 1 2,195 Apr-03-2020, 06:47 PM
Last Post: micseydel
  General question about serialization/deserialization in python local 1 1,929 Jan-28-2020, 04:35 AM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020