Popular Searches
Popular Course Categories
Popular Courses

Working with JSON Data and Serialization

Working with JSON Data and Serialization

File Handling and Data Serialization

Working with JSON Data and Serialization in Python

Course: Python Training

Topic: Working with JSON Data and Serialization

Course Link: Python Training Course at JustAcademy

Demo Link: Register for a Course Demo

Website: JustAcademy


1. Introduction to JSON Data

JSON stands for JavaScript Object Notation. It is a lightweight text-based data format used to store, exchange, and transfer structured information between applications. JSON is widely used in web development, REST APIs, configuration files, databases, and data-processing applications.

Python provides a built-in module called json that allows developers to convert Python objects into JSON-formatted data and convert JSON data back into Python objects.

For example, a Python application might store user details in a dictionary, convert that dictionary into JSON, save it to a file, and load it again when the application restarts.

Learning Objectives

  • Understand JSON syntax and data types.
  • Learn serialization and deserialization.
  • Use json.dumps(), json.loads(), json.dump(), and json.load().
  • Read and write JSON files.
  • Handle nested objects, lists, and dictionaries.
  • Configure JSON output using indentation and sorting.
  • Handle invalid JSON and serialization errors.
  • Build a practical JSON-based data storage application.

2. What Is JSON?

JSON represents structured data using key-value pairs, arrays, strings, numbers, Boolean values, and null values. Its simple syntax makes it easy for humans to read and for programs to process.

Example of JSON Data

{
    "name": "Aarav",
    "age": 24,
    "course": "Python",
    "is_enrolled": true,
    "skills": ["Python", "SQL", "HTML"],
    "address": {
        "city": "Mumbai",
        "country": "India"
    }
}

This example contains strings, a number, a Boolean value, an array, and a nested object.

Important JSON Syntax Rules

  • Object keys must be strings enclosed in double quotation marks.
  • String values must use double quotation marks.
  • Key-value pairs are separated by colons.
  • Items are separated by commas.
  • Objects are enclosed in curly braces {}.
  • Arrays are enclosed in square brackets [].
  • JSON uses lowercase true, false, and null.
  • Standard JSON does not support comments or trailing commas.

3. JSON Data Types and Python Equivalents

JSON supports a limited set of data types. Python's JSON module maps supported Python objects to their corresponding JSON representations.

JSON Type Example Python Equivalent
Object {"name": "Aarav"} dict
Array [10, 20, 30] list
String "Python" str
Number 25 int
Decimal number 19.5 float
Boolean true true True
Boolean false false False
Null null None

Example: Python Data Structure

student = {
    "name": "Meera",
    "age": 22,
    "marks": [85, 90, 88],
    "active": True,
    "graduation_year": None
}

print(student)

This is a normal Python dictionary. To exchange or store it as JSON, it must be converted into JSON-formatted text.

4. Understanding Serialization

Serialization is the process of converting a Python object into a format that can be stored or transmitted. When using JSON, serialization converts supported Python data structures into a JSON-formatted string or writes JSON data to a file.

Serialization is useful when:

  • Saving application settings.
  • Storing user preferences.
  • Sending data to a web API.
  • Exchanging data between Python and JavaScript applications.
  • Creating structured reports.
  • Preserving simple application data between program runs.

Serialization Flow

Python Object
     |
     v
JSON Serialization
     |
     v
JSON Text
     |
     v
File, API Request, or Network Transfer

5. Understanding Deserialization

Deserialization is the reverse process: converting JSON-formatted text or a JSON file into Python objects.

For example, a JSON object becomes a Python dictionary, while a JSON array becomes a Python list.

Deserialization Flow

JSON Text or File
        |
        v
JSON Deserialization
        |
        v
Python Dictionary, List, or Other Supported Type

Serialization and deserialization work together to make structured data portable between applications and persistent storage.

6. Introducing Python's json Module

The built-in json module provides functions for converting Python objects to JSON and JSON data back into Python objects. It does not require a separate package installation.

import json

student = {
    "name": "Aarav",
    "age": 24,
    "course": "Python"
}

json_text = json.dumps(student)
print(json_text)

Output:

{"name": "Aarav", "age": 24, "course": "Python"}

The json.dumps() function returns a string containing the JSON representation of the Python dictionary.

7. Using json.dumps() for Serialization

The json.dumps() function converts a Python object into a JSON-formatted string. The letter s in dumps refers to a string result.

Syntax

json.dumps(obj, indent=None, sort_keys=False)

The function supports additional options, including separators, Unicode handling, custom encoders, and circular-reference checking.

Example: Dictionary to JSON String

import json

employee = {
    "id": 101,
    "name": "Riya",
    "department": "Development",
    "salary": 45000
}

json_string = json.dumps(employee)

print(json_string)
print(type(json_string))

Output type:

<class 'str'>

Although the original data is a dictionary, the result of json.dumps() is a string.

Example: Serializing a List

import json

skills = ["Python", "Django", "SQL", "Git"]

json_string = json.dumps(skills)

print(json_string)

Output:

["Python", "Django", "SQL", "Git"]

8. Using json.loads() for Deserialization

The json.loads() function parses a JSON-formatted string and converts it into a corresponding Python object. The final s indicates that the input is a string.

Syntax

json.loads(json_string)

Example: JSON String to Dictionary

import json

json_string = '{"name": "Aarav", "age": 24, "course": "Python"}'

student = json.loads(json_string)

print(student)
print(student["name"])
print(type(student))

Output:

{'name': 'Aarav', 'age': 24, 'course': 'Python'}
Aarav
<class 'dict'>

The JSON object is converted into a Python dictionary, allowing normal dictionary operations such as accessing values by key.

Example: JSON Array to Python List

import json

json_string = '["Python", "SQL", "JavaScript"]'

skills = json.loads(json_string)

print(skills)
print(skills[0])

9. Difference Between dump(), dumps(), load(), and loads()

These four functions are the core tools for working with JSON in Python. Their names are similar, so it is important to understand when to use each one.

Function Input Output Purpose
json.dumps() Python object JSON string Serialize data into a string.
json.loads() JSON string Python object Deserialize a string.
json.dump() Python object and writable file Writes JSON to the file Serialize data directly into a file.
json.load() Readable JSON file Python object Read and deserialize JSON from a file.

Remember: Functions ending in s work with strings, while dump() and load() work with file-like objects.

10. Writing JSON Data to a File with json.dump()

The json.dump() function serializes a Python object and writes the resulting JSON data directly to a file object.

Example

import json

student = {
    "name": "Meera",
    "age": 22,
    "course": "Python",
    "skills": ["Programming", "Problem Solving"]
}

with open("student.json", "w", encoding="utf-8") as file:
    json.dump(student, file, indent=4)

print("Student data saved successfully.")

This example creates a file named student.json and writes the dictionary as formatted JSON. Opening the file with "w" replaces its previous content if the file already exists.

Example JSON File

{
    "name": "Meera",
    "age": 22,
    "course": "Python",
    "skills": [
        "Programming",
        "Problem Solving"
    ]
}

11. Reading JSON Data from a File with json.load()

The json.load() function reads JSON content from a file-like object and converts it into a Python object.

Example

import json

with open("student.json", "r", encoding="utf-8") as file:
    student = json.load(file)

print(student)
print("Name:", student["name"])
print("Course:", student["course"])

The resulting dictionary can be accessed and updated like any other Python dictionary.

12. Formatting JSON with indent

The indent parameter makes JSON output easier to read by adding indentation and line breaks. This is especially useful for configuration files, debugging, and reports.

Without Indentation

import json

data = {"name": "Riya", "age": 25, "city": "Mumbai"}

print(json.dumps(data))

Output:

{"name": "Riya", "age": 25, "city": "Mumbai"}

With Indentation

print(json.dumps(data, indent=4))

Output:

{
    "name": "Riya",
    "age": 25,
    "city": "Mumbai"
}

Use indent=2 or indent=4 according to the formatting conventions of your project.

13. Sorting JSON Object Keys

The sort_keys=True parameter sorts dictionary keys in the serialized JSON output. This is useful when comparing JSON output, creating predictable examples, or producing consistent configuration files.

import json

data = {
    "zebra": 1,
    "apple": 2,
    "mango": 3
}

print(json.dumps(data, indent=4, sort_keys=True))

Output:

{
    "apple": 2,
    "mango": 3,
    "zebra": 1
}

Sorting affects the output order of object keys. It does not sort the elements inside a list.

14. Compact JSON with separators

The separators parameter controls the characters used between JSON items and key-value pairs. It can reduce unnecessary whitespace when compact output is desired.

import json

data = {
    "name": "Aarav",
    "active": True,
    "score": 95
}

compact_json = json.dumps(data, separators=(",", ":"))

print(compact_json)

Output:

{"name":"Aarav","active":true,"score":95}

Compact JSON may be useful for transmission or storage where human readability is less important than minimizing whitespace.

15. Handling Unicode and Non-English Characters

JSON can represent text in many languages. By default, Python may escape non-ASCII characters in its JSON string output. Set ensure_ascii=False to preserve those characters directly in the output string.

import json

data = {
    "name": "Aarav",
    "city": "मुंबई",
    "greeting": "नमस्ते"
}

json_text = json.dumps(data, ensure_ascii=False, indent=4)

print(json_text)

When writing JSON to a file, use an appropriate text encoding such as UTF-8:

with open("indian_languages.json", "w", encoding="utf-8") as file:
    json.dump(data, file, ensure_ascii=False, indent=4)

16. Working with Nested JSON Data

JSON objects can contain other objects and arrays. This allows complex data structures to represent customers, orders, products, employees, and application settings.

Example Nested Data

import json

company = {
    "name": "Tech Solutions",
    "location": {
        "city": "Mumbai",
        "country": "India"
    },
    "employees": [
        {"name": "Aarav", "role": "Developer"},
        {"name": "Meera", "role": "Tester"}
    ]
}

json_text = json.dumps(company, indent=4)
print(json_text)

Accessing Nested Values

print(company["location"]["city"])
print(company["employees"][0]["name"])
print(company["employees"][1]["role"])

Output:

Mumbai
Aarav
Tester

Use the appropriate dictionary key or list index to access the required nested value. For data from external sources, check that expected keys and data types are present before accessing them.

17. Updating JSON Data

After loading JSON into Python, you can update its values using normal Python operations and then serialize the updated object back to a file.

import json

with open("student.json", "r", encoding="utf-8") as file:
    student = json.load(file)

student["age"] = 23
student["skills"].append("Django")

with open("student.json", "w", encoding="utf-8") as file:
    json.dump(student, file, indent=4)

print("Student record updated.")

This example loads the file into memory, modifies the dictionary, and writes the entire updated object back to the file. The write operation replaces the old file content, so use suitable safeguards for important data.

18. Converting JSON Data to Python Types

When JSON is decoded, the resulting Python data types follow the JSON-to-Python mapping. Understanding these conversions helps prevent unexpected type errors.

import json

json_text = '''
{
    "count": 10,
    "price": 49.99,
    "available": true,
    "description": null,
    "tags": ["python", "json"]
}
'''

data = json.loads(json_text)

print(type(data["count"]))
print(type(data["price"]))
print(type(data["available"]))
print(data["description"])
print(type(data["tags"]))

The integer remains an int, the decimal becomes a float, the Boolean becomes True, JSON null becomes None, and the array becomes a Python list.

19. Handling Invalid JSON with JSONDecodeError

JSON input may contain syntax errors, such as missing quotation marks, missing commas, or trailing commas. When parsing invalid JSON, Python raises json.JSONDecodeError.

Example of Invalid JSON

import json

invalid_json = '{"name": "Aarav", "age": 24,}'

try:
    data = json.loads(invalid_json)
except json.JSONDecodeError as error:
    print("Invalid JSON data.")
    print("Details:", error)

The trailing comma before the closing brace is not valid in standard JSON.

Handling an Invalid JSON File

import json

try:
    with open("settings.json", "r", encoding="utf-8") as file:
        settings = json.load(file)
except FileNotFoundError:
    print("Settings file was not found.")
except json.JSONDecodeError as error:
    print("Settings file contains invalid JSON:", error)
except OSError as error:
    print("Unable to read settings file:", error)

This example distinguishes missing files, invalid JSON syntax, and broader file-system errors.

20. Handling Serialization Errors

Not every Python object can be converted to JSON automatically. Common unsupported objects include sets, file objects, functions, and custom class instances.

Example: Unsupported Set

import json

data = {
    "skills": {"Python", "SQL", "Django"}
}

try:
    print(json.dumps(data))
except TypeError as error:
    print("Serialization failed:", error)

A set is not directly supported by the standard JSON encoder. If order is unimportant and a JSON array is appropriate, convert the set to a list first.

data = {
    "skills": sorted({"Python", "SQL", "Django"})
}

print(json.dumps(data, indent=4))

Choose conversions carefully because converting a data type may change its original behavior or information.

21. Serializing Dates and Datetime Objects

The standard JSON encoder does not serialize Python date and datetime objects automatically. A common solution is to convert date values into ISO 8601 strings.

import json
from datetime import datetime, timezone

record = {
    "event": "Training Session",
    "created_at": datetime.now(timezone.utc).isoformat()
}

json_text = json.dumps(record, indent=4)
print(json_text)

ISO-formatted timestamps are easier to exchange between systems than arbitrary display strings. If the application later needs a real datetime object, parse the stored string explicitly.

Using a Custom Default Function

import json
from datetime import date

def json_default(value):
    if isinstance(value, date):
        return value.isoformat()
    raise TypeError(f"Unsupported type: {type(value).__name__}")

data = {
    "name": "Meera",
    "joining_date": date(2026, 1, 15)
}

json_text = json.dumps(data, default=json_default, indent=4)
print(json_text)

The custom function converts supported date objects to strings and raises TypeError for unsupported types instead of silently discarding data.

22. Serializing Custom Python Objects

Instances of custom classes cannot generally be passed directly to json.dumps(). Convert the object's relevant attributes into a dictionary or implement a controlled custom encoder.

Example Using a Dictionary

import json

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

student = Student("Aarav", 24)

student_data = {
    "name": student.name,
    "age": student.age
}

print(json.dumps(student_data, indent=4))

Converting an object to a dictionary makes the JSON representation explicit and helps avoid accidentally exposing internal attributes.

23. Validating JSON Data After Loading

Valid JSON is not necessarily valid application data. A JSON document can have correct syntax but still omit required fields or contain unexpected values.

import json

json_text = '{"name": "Aarav", "age": 24}'

data = json.loads(json_text)

if not isinstance(data, dict):
    raise ValueError("Expected a JSON object.")

if "name" not in data or not isinstance(data["name"], str):
    raise ValueError("A valid name is required.")

if "age" not in data or not isinstance(data["age"], int):
    raise ValueError("Age must be an integer.")

print("Data structure is valid.")

For production systems, validate required fields, allowed values, data types, string lengths, numeric ranges, and business rules. Consider a schema-validation library when the data structure is complex.

24. JSON and REST APIs

JSON is widely used by REST APIs to exchange data between clients and servers. A client may send a JSON request body to create a resource, and the server may return a JSON response.

Example JSON API Payload

{
    "customer_id": 501,
    "product": "Laptop",
    "quantity": 2,
    "delivery": {
        "city": "Mumbai",
        "postal_code": "400001"
    }
}

In a Python application, json.dumps() can prepare a JSON string for a compatible API client, while a response body containing JSON can be decoded using the client's JSON support or json.loads().

When working with APIs, also check HTTP status codes, authentication, timeouts, and the structure of the response. Do not assume every server response contains valid JSON.

25. JSON vs Python Dictionary

JSON and Python dictionaries may look similar, but they are not the same thing. A dictionary is a Python data structure, while JSON is a text-based interchange format.

Feature Python Dictionary JSON Object
Representation Python object in memory Text representation of structured data
Keys Can be supported hashable Python objects Must be strings in standard JSON syntax
Boolean values True and False true and false
Null value None null
Use Program logic and in-memory data Storage and data exchange
Conversion Use json.dumps() to serialize supported data Use json.loads() to parse JSON text

JSON object keys are strings. When a Python dictionary with non-string keys is serialized, supported keys may be converted to strings, which means a round trip may not reproduce the original dictionary exactly.

26. JSON vs Pickle

Python offers other serialization tools, including pickle. JSON is generally more suitable for interoperable data exchange, while pickle can preserve a wider range of Python-specific objects.

Feature JSON Pickle
Human readability Usually readable text Typically binary and not human-readable
Cross-language support Widely supported across languages Primarily Python-specific
Supported objects Limited set of standard data types by default Supports many Python-specific object types
Typical use APIs, settings, structured data files Trusted Python-specific object persistence
Security consideration Validate data and limit untrusted input size Never unpickle untrusted or unauthenticated data

Security warning: Unpickling untrusted data can execute arbitrary code. JSON does not have the same object-construction behavior by default, but untrusted JSON can still cause problems if it is extremely large or if the application uses the data unsafely.

27. Best Practices for JSON Serialization

  • Use the built-in json module for standard JSON operations.
  • Use dump() and load() when working directly with files.
  • Use dumps() and loads() when working with JSON strings.
  • Specify UTF-8 when opening JSON text files.
  • Use indent for readable configuration and report files.
  • Use sort_keys=True when stable key ordering is useful.
  • Handle JSONDecodeError when parsing external or editable JSON.
  • Validate the decoded structure before using its values.
  • Do not silently skip unsupported values without understanding the consequences.
  • Do not place passwords, API keys, or other secrets in publicly accessible JSON files.
  • Limit the size of untrusted JSON input to reduce resource-exhaustion risks.
  • Use a safe update strategy when writing important files, such as writing to a temporary file before replacing the original.

28. Mini Project: Student Records Using JSON

Project Objective: Build a small student-record application that stores student information in a JSON file and supports adding, viewing, and searching records.

Project Requirements

  • Store student records as a list of dictionaries.
  • Save the list to a JSON file.
  • Load existing records when the program starts.
  • Add new student records.
  • Search for a student using their ID.
  • Handle missing files and malformed JSON.
  • Use indentation for readable JSON output.

Sample Implementation

import json
from pathlib import Path

DATA_FILE = Path("students.json")

def load_students():
    if not DATA_FILE.exists():
        return []

    try:
        with DATA_FILE.open("r", encoding="utf-8") as file:
            data = json.load(file)
    except json.JSONDecodeError as error:
        raise ValueError("The student file contains invalid JSON.") from error

    if not isinstance(data, list):
        raise ValueError("Student data must be a JSON list.")

    return data

def save_students(students):
    with DATA_FILE.open("w", encoding="utf-8") as file:
        json.dump(students, file, indent=4, ensure_ascii=False)

def add_student(students, student_id, name, course):
    if any(student.get("id") == student_id for student in students):
        raise ValueError("A student with this ID already exists.")

    students.append({
        "id": student_id,
        "name": name,
        "course": course
    })

def find_student(students, student_id):
    for student in students:
        if student.get("id") == student_id:
            return student
    return None

try:
    students = load_students()

    add_student(students, 101, "Aarav", "Python")
    save_students(students)

    result = find_student(students, 101)
    print("Found student:", result)

except (ValueError, OSError) as error:
    print("Could not process student records:", error)

This is a learning example. In a production application, validate every loaded record, handle duplicate IDs and repeated program runs appropriately, and consider atomic file replacement to protect important data from partial writes.

29. Practice Exercises

  1. Create a Python dictionary containing personal or course details and serialize it with json.dumps().
  2. Convert a JSON string into a Python dictionary using json.loads().
  3. Write a nested dictionary to a JSON file using json.dump().
  4. Read the saved JSON file using json.load().
  5. Format JSON output using indent=4.
  6. Sort JSON object keys using sort_keys=True.
  7. Save Unicode text using ensure_ascii=False and UTF-8 encoding.
  8. Handle malformed JSON using json.JSONDecodeError.
  9. Serialize a date object using a custom default function.
  10. Build a small configuration-file reader that validates required keys.
  11. Extend the student-record project to support updating and deleting records.

30. Interview Questions and Answers

Q1. What is JSON?

JSON is a lightweight text-based data format used to represent structured information and exchange it between applications.

Q2. What is serialization?

Serialization converts a Python object into a format that can be stored or transmitted, such as JSON text.

Q3. What is deserialization?

Deserialization converts serialized data, such as JSON text, back into a Python object.

Q4. What is the difference between dumps() and dump()?

dumps() returns JSON text as a string, while dump() writes JSON data to a file-like object.

Q5. What is the difference between loads() and load()?

loads() parses a JSON string, while load() reads JSON data from a file-like object.

Q6. Which Python data type represents a JSON object?

A JSON object is normally decoded into a Python dictionary.

Q7. What does indent do in json.dumps()?

It formats the output with indentation and line breaks to make JSON easier to read.

Q8. How do you handle invalid JSON?

Catch json.JSONDecodeError around the parsing operation and provide a useful error message or recovery process.

Q9. Can every Python object be serialized to JSON automatically?

No. Custom objects, sets, dates, file objects, and many other types require an explicit conversion strategy or custom encoder.

Q10. Why is JSON commonly used in APIs?

It is lightweight, readable, widely supported, and can represent common structured data across different programming languages.

Q11. What is the difference between JSON and a Python dictionary?

A dictionary is an in-memory Python object. JSON is a text format that can represent data in a language-independent way.

Q12. Why should JSON data be validated after parsing?

Valid JSON syntax does not guarantee that required fields, expected types, or application rules are satisfied.

31. Quick Revision Checklist

  • JSON: A text-based format for structured data.
  • Serialization: Python object to JSON representation.
  • Deserialization: JSON data to Python object.
  • json.dumps(): Convert a Python object to a JSON string.
  • json.loads(): Parse a JSON string.
  • json.dump(): Write JSON to a file.
  • json.load(): Read JSON from a file.
  • indent: Format JSON for readability.
  • sort_keys=True: Sort output object keys.
  • ensure_ascii=False: Preserve non-ASCII characters directly in output text.
  • JSONDecodeError: Handle invalid JSON syntax.
  • Validation: Check required fields and data types after parsing.
  • Security: Limit untrusted input size and never expose sensitive information unnecessarily.

32. Conclusion

Working with JSON data and serialization is an essential Python skill for file storage, configuration management, API communication, and data exchange. The json module provides convenient functions for converting Python objects to JSON strings, writing JSON files, and decoding JSON back into usable Python data structures.

By understanding the differences between dump(), dumps(), load(), and loads(), developers can choose the correct approach for each task. Combining serialization with error handling, data validation, appropriate formatting, and safe storage practices helps create reliable applications.

Continue learning through the Python Training Course at JustAcademy, register for a course demo, or explore the JustAcademy website.

Official Reference: Python JSON Module Documentation

whatsapp