18.7. JSON Recap

  • JavaScript Object Notation

  • The most popular format for data exchange

  • JSON format is similar to dict notation in Python

  • Fields are always enclosed only by double quote " character

  • Instead of True there is true (lowercase)

  • Instead of False there is false (lowercase)

  • Instead of None there is null

  • list is known as array (despite the same syntax)

  • JSON has no tuple or set

  • Coma , is not allowed after the last element in list or object

  • Object of type tuple will serialize as list

  • Object of type set is not JSON serializable

  • dict is known as object (despite the same syntax)

  • Coma , is not allowed after the last element in list or object

  • camelCase is convention, although snake_case is also valid

  • Fields are always enclosed only by double quote " character

  • Unicode characters are stored as unicode entities ("cze\\u015b\\u0107")

  • JSON can be minified to save space for network transmission

  • Minified JSON is not human readable

  • Use python -m json.tool to prettify (humanize) output

18.7.1. Assignments

# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% About
# - Name: JSON File Load
# - Difficulty: easy
# - Lines: 2
# - Minutes: 5

# %% English
# 1. Read data from `FILE`
# 2. Convert data to `result: list[tuple]`
# 3. Add header as a first line
# 4. Run doctests - all must succeed

# %% Polish
# 1. Odczytaj dane z pliku `FILE`
# 2. Przekonwertuj dane do `result: list[tuple]`
# 3. Dodaj nagłówek jako pierwszą linię
# 4. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - `with open(mode='rt') as file:`
# - `json.load()`
# - `dict.keys()`
# - `dict.values()`
# - `tuple()`
# - `list.append()`
# - `list.extend()`

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> from os import remove
 >>> remove(FILE)

>>> assert result is not Ellipsis, \
'Assign result to variable: `result`'
>>> assert type(result) is list, \
'Variable `result` has invalid type, should be list'
>>> assert len(result) > 0, \
'Variable `result` should not be empty'
>>> assert all(type(row) is tuple for row in result), \
'Variable `result` should be a list[tuple]'

>>> from pprint import pprint
>>> pprint(result)
[('sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'species'),
 (5.8, 2.7, 5.1, 1.9, 'virginica'),
 (5.1, 3.5, 1.4, 0.2, 'setosa'),
 (5.7, 2.8, 4.1, 1.3, 'versicolor'),
 (6.3, 2.9, 5.6, 1.8, 'virginica'),
 (6.4, 3.2, 4.5, 1.5, 'versicolor'),
 (4.7, 3.2, 1.3, 0.2, 'setosa'),
 (7.0, 3.2, 4.7, 1.4, 'versicolor'),
 (7.6, 3.0, 6.6, 2.1, 'virginica'),
 (4.9, 3.0, 1.4, 0.2, 'setosa')]
"""

import json


FILE = r'_temporary.json'

with open(FILE, mode='wt') as file:
    file.write("""[
{"sepal_length": 5.8, "sepal_width": 2.7, "petal_length": 5.1, "petal_width": 1.9, "species": "virginica"},
{"sepal_length": 5.1, "sepal_width": 3.5, "petal_length": 1.4, "petal_width": 0.2, "species": "setosa"},
{"sepal_length": 5.7, "sepal_width": 2.8, "petal_length": 4.1, "petal_width": 1.3, "species": "versicolor"},
{"sepal_length": 6.3, "sepal_width": 2.9, "petal_length": 5.6, "petal_width": 1.8, "species": "virginica"},
{"sepal_length": 6.4, "sepal_width": 3.2, "petal_length": 4.5, "petal_width": 1.5, "species": "versicolor"},
{"sepal_length": 4.7, "sepal_width": 3.2, "petal_length": 1.3, "petal_width": 0.2, "species": "setosa"},
{"sepal_length": 7.0, "sepal_width": 3.2, "petal_length": 4.7, "petal_width": 1.4, "species": "versicolor"},
{"sepal_length": 7.6, "sepal_width": 3.0, "petal_length": 6.6, "petal_width": 2.1, "species": "virginica"},
{"sepal_length": 4.9, "sepal_width": 3.0, "petal_length": 1.4, "petal_width": 0.2, "species": "setosa"}
]""")

# type: list[tuple]
result = ...


# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% About
# - Name: JSON File Blanks
# - Difficulty: medium
# - Lines: 13
# - Minutes: 13

# %% English
# 1. Read data from `FILE`
# 2. Convert data to `result: list[tuple]`
# 3. Add sorted header as a first line
# 4. Replace empty values with `None`
# 5. Run doctests - all must succeed

# %% Polish
# 1. Odczytaj dane z pliku `FILE`
# 2. Przekonwertuj dane do `result: list[tuple]`
# 3. Dodaj posortowany nagłówek jako pierwszą linia
# 4. Zamień wartości puste na `None`
# 5. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - `with open(mode='rt') as file:`
# - `json.load()`
# - `dict.keys()`
# - `dict.values()`
# - `dict.get(default=None)`
# - `dict comprehension`
# - `tuple()`
# - `set()`
# - `set.update()`
# - `set.add()`
# - `sorted()`
# - `list.append()`
# - `list.extend()`

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> from os import remove
>>> remove(FILE)

>>> assert result is not Ellipsis, \
'Assign result to variable: `result`'
>>> assert type(result) is list, \
'Variable `result` has invalid type, should be list'
>>> assert len(result) > 0, \
'Variable `result` should not be empty'
>>> assert all(type(row) is tuple for row in result), \
'Variable `result` should be a list[tuple]'

>>> from pprint import pprint
>>> pprint(result)
[('petal_length', 'petal_width', 'sepal_length', 'sepal_width', 'species'),
 (None, None, None, None, 'virginica'),
 (1.4, 0.2, None, 3.5, 'setosa'),
 (4.1, 1.3, 5.7, None, 'versicolor'),
 (None, 1.8, 6.3, 2.9, 'virginica'),
 (4.5, None, 6.4, 3.2, 'versicolor'),
 (None, None, 4.7, 3.2, 'setosa'),
 (4.7, 1.4, None, None, 'versicolor'),
 (None, 2.1, 7.6, None, 'virginica'),
 (1.4, None, None, 3.0, 'setosa')]
"""

import json


FILE = r'_temporary.json'

with open(FILE, mode='wt') as file:
    file.write("""[
{"species": "virginica"},
{"sepal_width": 3.5, "petal_length": 1.4, "petal_width": 0.2, "species": "setosa"},
{"sepal_length": 5.7, "petal_length": 4.1, "petal_width": 1.3, "species": "versicolor"},
{"sepal_length": 6.3, "sepal_width": 2.9, "petal_width": 1.8, "species": "virginica"},
{"sepal_length": 6.4, "sepal_width": 3.2, "petal_length": 4.5, "species": "versicolor"},
{"sepal_length": 4.7, "sepal_width": 3.2, "species": "setosa"},
{"petal_length": 4.7, "petal_width": 1.4, "species": "versicolor"},
{"sepal_length": 7.6, "petal_width": 2.1, "species": "virginica"},
{"sepal_width": 3.0, "petal_length": 1.4, "species": "setosa"}
]""")

# type: list[tuple]
result = ...