Working with JSON
Working with JSON: Advanced Serialization
JavaScript Object Notation (JSON) is the lingua franca of modern web services, RESTful APIs, configuration files, and distributed microservice messaging. Standardized in RFC 8259, JSON is text-based, language-agnostic, and safe against arbitrary code execution.
While basic usage of Python's built-in json module is straightforward, enterprise applications require advanced techniques: custom JSON encoders for domain models, object_hook deserialization, high-density minification, and handling unsupported types like datetime, UUID, and Decimal.
1. Type Mappings & Limitations
Python and JSON share similar primitives, but their types do not map 1:1:
| Python Type | JSON Type | Nuance / Caveats |
|---|---|---|
dict | Object | JSON keys must be strings; integer dict keys {1: "a"} are coerced to {"1": "a"} |
list, tuple | Array | Tuples serialize to JSON arrays and deserialize back as Python lists |
str | String | UTF-8 encoded |
int, float | Number | JSON does not distinguish float vs int; NaN and Infinity are non-standard |
True, False | true, false | Lowercase in JSON |
None | null | Lowercase in JSON |
datetime, Decimal, UUID | TypeError | Unsupported by default: requires custom encoder |
2. Advanced Serialization with Custom JSONEncoder
When passing non-standard objects into json.dumps(), Python raises a runtime TypeError: Object of type X is not JSON serializable.
To handle complex domain entities, subclass json.JSONEncoder and override the default() method:
Visual Architecture & Process Flow
How data and code flow step-by-step
3. Custom Deserialization with object_hook
When reading JSON via json.loads(), all objects become standard dictionaries. If you want JSON dictionaries to be deserialized directly into typed domain classes or parse ISO dates automatically, provide an object_hook:
4. Formatting: Minification vs Pretty-Printing
JSON formatting parameters allow you to optimize for human readability or network bandwidth:
5. Architectural Summary Table
| Parameter | Function | Purpose |
|---|---|---|
cls=CustomEncoder | json.dumps() | Plugs in custom class to serialize arbitrary object types |
object_hook=func | json.loads() | Intercepts dictionary parsing to instantiate custom objects |
indent=N | json.dumps() | Indents JSON with $N$ spaces for readability |
separators=(",", ":") | json.dumps() | Strips unnecessary whitespace for minified network payload |
sort_keys=True | json.dumps() | Sorts dictionary keys alphabetically for deterministic output |
Multiple Choice Questions
1.
What exception is raised when calling json.dumps({"time": datetime.datetime.now()}) without a custom serializer? A. ValueError B. TypeError: Object of type datetime is not JSON serializable C. KeyError D. SerializationError
json library only supports basic primitives by default. Passing unsupported objects like datetime raises a TypeError.2.
Which method must be overridden when creating a custom subclass of json.JSONEncoder? A. serialize(self, obj) B. default(self, obj) C. encode_object(self, obj) D. to_json(self, obj)
json.JSONEncoder, the default(self, obj) method is called for any object that the standard serializer cannot handle, allowing custom conversion into JSON-serializable types.3.
What is the purpose of the object_hook parameter in json.loads()? A. To hook into the network socket. B. To intercept every parsed JSON object dictionary and optionally transform it into a custom Python class instance. C. To prevent JSON injection attacks. D. To validate schema types in SQLite.
object_hook accepts a callable that is invoked with the result of any JSON object decoded as a dictionary, enabling automated conversion into custom domain objects.4.
How can you produce the most compact, minified JSON string for transmission over a network socket? A. json.dumps(data, compress=True) B. json.dumps(data, separators=(",", ":")) C. json.dumps(data, indent=0) D. json.dumps(data, minified=True)
separators=(",", ":") removes trailing spaces after commas and colons, producing a compact, minified wire payload.5.
What happens to a Python tuple when it is serialized to JSON and then deserialized back to Python? A. It remains a tuple. B. It is converted into a list. C. It is converted into a set. D. It raises a ValueError.
list objects.Working with YAML
Continue learning with hands-on practice, examples, and exercises in the upcoming topic.
Related Lessons
| Previous Lesson | Next Lesson |
|---|---|
| Pickle Module | Working with YAML |
Practice Quiz
Test your understanding of this lesson with 5 questions. Each question has one correct answer.