mirror of
https://github.com/kennethreitz/dive-into-python3.git
synced 2026-06-05 15:00:18 +00:00
raise TypeError at end of to_json custom serializer function
This commit is contained in:
+5
-2
@@ -458,11 +458,13 @@ def protocol_version(file_object):
|
||||
<a>def to_json(python_object): <span class=u>①</span></a>
|
||||
<a> if isinstance(python_object, bytes): <span class=u>②</span></a>
|
||||
<a> return {'__class__': 'bytes',
|
||||
'__value__': list(python_object)} <span class=u>③</span></a></code></pre>
|
||||
'__value__': list(python_object)} <span class=u>③</span></a>
|
||||
<a> raise TypeError <span class=u>④</span></a></code></pre>
|
||||
<ol>
|
||||
<li>To define your own “mini-serialization format” for a datatype that <abbr>JSON</abbr> doesn’t support natively, just define a function that takes a Python object as a parameter. This Python object will be the actual object that the <code>json.dump()</code> function is unable to serialize by itself — in this case, the <code>bytes</code> object <code>b'\xDE\xD5\xB4\xF8'</code>.
|
||||
<li>Your custom serialization function should check the type of the Python object that the <code>json.dump()</code> function passed to it. This is not strictly necessary if your function only serializes one datatype, but it makes it crystal clear what case your function is covering, and it makes it easier to extend if you need to add serializations for more datatypes later.
|
||||
<li>In this case, I’ve chosen to convert a <code>bytes</code> object into a dictionary. The <code>__class__</code> key will hold the original datatype (as a string, <code>'bytes'</code>), and the <code>__value__</code> key will hold the actual value. Of course this can’t be a <code>bytes</code> object; the entire point is to convert it into something that can be serialized in <abbr>JSON</abbr>! A <code>bytes</code> object is just a sequence of integers; each integer is somewhere in the range 0–255. We can use the <code>list()</code> function to convert the <code>bytes</code> object into a list of integers. So <code>b'\xDE\xD5\xB4\xF8'</code> becomes <code>[222, 213, 180, 248]</code>. (Do the math! It works! The byte <code>\xDE</code> in hexadecimal is 222 in decimal, <code>\xD5</code> is 213, and so on.)
|
||||
<li>This line is important. The data structure you’re serializing may contain types that neither the built-in <abbr>JSON</abbr> serializer nor your custom serializer can handle. In this case, your custom serializer must raise a <code>TypeError</code> so that the <code>json.dump()</code> function knows that your custom serializer did not recognize the type.
|
||||
</ol>
|
||||
|
||||
<p>That’s it; you don’t need to do anything else. In particular, this custom serialization function <em>returns a Python dictionary</em>, not a string. You’re not doing the entire serializing-to-<abbr>JSON</abbr> yourself; you’re only doing the converting-to-a-supported-datatype part. The <code>json.dump()</code> function will do the rest.
|
||||
@@ -506,7 +508,8 @@ def to_json(python_object):
|
||||
'__value__': time.asctime(python_object)} <span class=u>②</span></a>
|
||||
if isinstance(python_object, bytes):
|
||||
return {'__class__': 'bytes',
|
||||
'__value__': list(python_object)}</code></pre>
|
||||
'__value__': list(python_object)}
|
||||
raise TypeError</code></pre>
|
||||
<ol>
|
||||
<li>Adding to our existing <code>customserializer.to_json()</code> function, we need to check whether the Python object (that the <code>json.dump()</code> function is having trouble with) is a <code>time.struct_time</code>.
|
||||
<li>If so, we’ll do something similar to the conversion we did with the <code>bytes</code> object: convert the <code>time.struct_time</code> object to a dictionary that only contains <abbr>JSON</abbr>-serializable values. In this case, the easiest way to convert a datetime into a <abbr>JSON</abbr>-serializable value is to convert it to a string with the <code>time.asctime()</code> function. The <code>time.asctime()</code> function will convert that nasty-looking <code>time.struct_time</code> into the string <code>'Fri Mar 27 22:20:42 2009'</code>.
|
||||
|
||||
Reference in New Issue
Block a user