2. JSON Serialization

2.1. JSON syntax

Format JSON jest podobny do zapisu dict w Python, ale różni się:

  • nie może być przecinka po ostatnim elemencie list

  • zawsze stosowany jest podwójny cudzysłów

  • true i false jest pisane małymi literami

  • zamiast None jest null

  • konwencją jest stosowanie camelCase a nie snake_case, ale oba są poprawne

2.1.1. Example

[
    {"sepalLength": 5.1, "sepalWidth": 3.5, "petalLength": 1.4, "petalWidth": 0.2, "species": "setosa"},
    {"sepalLength": 4.9, "sepalWidth": 3.0, "petalLength": 1.4, "petalWidth": 0.2, "species": "setosa"},
    {"sepalLength": false, "sepalWidth": true, "petalLength": null, "petalWidth": 0.2, "species": null}
]

2.2. JSON Serialization of simple objects

To file:

  • json.dump(DATA, file)

  • json.load(DATA, file)

To string:

  • json.dumps(DATA)

  • json.loads(DATA)

2.2.1. Serialize to JSON

Listing 212. Serializing to JSON
import json


DATA = {
    'first_name': 'Jan',
    'last_name': 'Twardowski'
}

output = json.dumps(DATA)
print(output)
# '{"first_name": "Jan", "last_name": "Twardowski"}'

2.2.2. Deserialize from JSON

Listing 213. Deserialize from JSON
import json


DATA = '{"first_name": "Jan", "last_name": "Twardowski"}'

output = json.loads(DATA)
print(output)
# {
#     'first_name': 'Jan',
#     'last_name': 'Twardowski'
# }

2.3. Serializing datetime and date

2.3.1. Encoding datetime and date

  • Encoder will be used, when standard procedure fails

Listing 214. Exception during encoding datetime
from datetime import datetime, date
import json


DATA = {
    'name': 'Jan Twardowski',
    'date': date(1961, 4, 12),
    'datetime': datetime(1969, 7, 21, 2, 56, 15),
}

output = json.dumps(DATA)
# TypeError: Object of type date is not JSON serializable
Listing 215. Encoding datetime and date
from datetime import datetime, date
import json


DATA = {
    'name': 'Jan Twardowski',
    'date': date(1961, 4, 12),
    'datetime': datetime(1969, 7, 21, 2, 56, 15),
}


class JSONDatetimeEncoder(json.JSONEncoder):
    def default(self, value):

        if isinstance(value, datetime):
            return value.strftime('%Y-%m-%dT%H:%M:%S.%fZ')

        if isinstance(value, date):
            return value.strftime('%Y-%m-%d')


output = json.dumps(DATA, cls=JSONDatetimeEncoder)
print(output)
# '{"name": "Jan Twardowski", "date": "1961-04-12", "datetime": "1969-07-21T02:56:15.000Z"}'

2.3.2. Decoding datetime and date

Listing 216. Simple loading returns str not datetime or date
import json


DATA = '{"name": "Jan Twardowski", "date": "1961-04-12", "datetime": "1969-07-21T02:56:15.000Z"}'

output = json.loads(DATA)
print(output)
# {
#     'name': 'Jan Twardowski',
#     'date': '1961-04-12',
#     'datetime': '1969-07-21T02:56:15.000Z',
# }
Listing 217. Decoding datetime and date
from datetime import datetime, timezone
import json

DATA = '{"name": "Jan Twardowski", "date": "1961-04-12", "datetime": "1969-07-21T02:56:15.000Z"}'


class JSONDatetimeDecoder(json.JSONDecoder):
    DATE_FIELDS = ['date', 'date_of_birth']
    DATETIME_FIELDS = ['datetime']

    def __init__(self):
        super().__init__(object_hook=self.default)

    def default(self, output: dict) -> dict:
        for field, value in output.items():

            if field in self.DATE_FIELDS:
                value = datetime.strptime(value, '%Y-%m-%d').date()

            if field in self.DATETIME_FIELDS:
                value = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ').replace(tzinfo=timezone.utc)

            output[field] = value
        return output


output = json.loads(DATA, cls=JSONDatetimeDecoder)
print(output)
# {
#     'name': 'Jan Twardowski',
#     'date': date(1961, 4, 12),
#     'datetime': datetime(1969, 7, 21, 2, 56, 15, tzinfo=datetime.timezone.utc),
# }

2.4. Serializing objects

2.4.1. Encoding objects

  • Encoder will be used, when standard procedure fails

Listing 218. Encoding objects to JSON
import json


class Contact:
    def __init__(self, first_name, last_name, addresses=()):
        self.first_name = first_name
        self.last_name = last_name
        self.addresses = addresses


class Address:
    def __init__(self, center, location):
        self.center = center
        self.location = location


DATA = [
    Contact(first_name='Jan', last_name='Twardowski', addresses=(
        Address(center='Johnson Space Center', location='Houston, TX'),
        Address(center='Kennedy Space Center', location='Merritt Island, FL'),
        Address(center='Jet Propulsion Laboratory', location='Pasadena, CA'),
    )),
    Contact(first_name='Mark', last_name='Watney'),
    Contact(first_name='Melissa', last_name='Lewis', addresses=()),
]


class JSONObjectEncoder(json.JSONEncoder):
    def default(self, obj):
        result = obj.__dict__
        result['__class_name__'] = obj.__class__.__name__
        return result


output = json.dumps(DATA, cls=JSONObjectEncoder)

print(output)
# [
#    {"__class_name__":"Contact", "first_name":"Jan", "last_name":"Twardowski", "addresses":[
#          {"__class_name__":"Address", "center":"JSC", "location":"Houston, TX"},
#          {"__class_name__":"Address", "center":"KSC", "location":"Merritt Island, FL"},
#          {"__class_name__":"Address", "center":"JPL", "location":"Pasadena, CA"},
#    {"__class_name__":"Contact", "first_name":"Mark", "last_name":"Watney", "addresses":[]},
#    {"__class_name__":"Contact", "first_name":"Melissa", "last_name":"Lewis", "addresses":[]}
# ]

2.4.2. Decoding objects

Listing 219. Decoding objects from JSON
import json
import sys


CURRENT_MODULE = sys.modules[__name__]
DATA = """
[
   {"__class_name__":"Contact", "first_name":"Jan", "last_name":"Twardowski", "addresses":[
         {"__class_name__":"Address", "center":"JSC", "location":"Houston, TX"},
         {"__class_name__":"Address", "center":"KSC", "location":"Merritt Island, FL"},
         {"__class_name__":"Address", "center":"JPL", "location":"Pasadena, CA"},
   {"__class_name__":"Contact", "first_name":"Mark", "last_name":"Watney", "addresses":[]},
   {"__class_name__":"Contact", "first_name":"Melissa", "last_name":"Lewis", "addresses":[]}
]
"""


class Contact:
    def __init__(self, first_name, last_name, addresses=()):
        self.first_name = first_name
        self.last_name = last_name
        self.addresses = addresses


class Address:
    def __init__(self, center, location):
        self.center = center
        self.location = location


class JSONObjectDecoder(json.JSONDecoder):
    def __init__(self):
        super().__init__(object_hook=self.default)

    def default(self, obj):
        class_name = obj.pop('__class_name__')
        cls = getattr(CURRENT_MODULE, class_name)
        return cls(**obj)


output = json.loads(DATA, cls=JSONObjectDecoder)
print(output)
# [
#     Contact(first_name='Jan', last_name='Twardowski', addresses=(
#         Address(center='Johnson Space Center', location='Houston, TX'),
#         Address(center='Kennedy Space Center', location='Merritt Island, FL'),
#         Address(center='Jet Propulsion Laboratory', location='Pasadena, CA'),
#     )),
#     Contact(first_name='Mark', last_name='Watney'),
#     Contact(first_name='Melissa', last_name='Lewis', addresses=()),
# ]

2.5. Pretty Printing JSON

2.5.1. JSON can be compressed

  • It is not very readable

$ URL='https://raw.githubusercontent.com/AstroMatt/book-python/master/serialization/data/iris.json'
$ curl $URL

[{"sepalLength":5.1,"sepalWidth":3.5,"petalLength":1.4,"petalWidth":0.2,"species":"setosa"},{"sepalLength":4.9,"sepalWidth":3,"petalLength":1.4,"petalWidth":0.2,"species":"setosa"},{"sepalLength":4.7,"sepalWidth":3.2,"petalLength":1.3,"petalWidth":0.2,"species":"setosa"},{"sepalLength":4.6,"sepalWidth":3.1,"petalLength":1.5,"petalWidth":0.2,"species":"setosa"},{"sepalLength":5,"sepalWidth":3.6,"petalLength":1.4,"petalWidth":0.2,"species":"setosa"},{"sepalLength":5.4,"sepalWidth":3.9,"petalLength":1.7,"petalWidth":0.4,"species":"setosa"},{"sepalLength":4.6,"sepalWidth":3.4,"petalLength":1.4,"petalWidth":0.3,"species":"setosa"},{"sepalLength":5,"sepalWidth":3.4,"petalLength":1.5,"petalWidth":0.2,"species":"setosa"},{"sepalLength":4.4,"sepalWidth":2.9,"petalLength":1.4,"petalWidth":0.2,"species":"setosa"},{"sepalLength":4.9,"sepalWidth":3.1,"petalLength":1.5,"petalWidth":0.1,"species":"setosa"},{"sepalLength":7,"sepalWidth":3.2,"petalLength":4.7,"petalWidth":1.4,"species":"versicolor"},{"sepalLength":6.4,"sepalWidth":3.2,"petalLength":4.5,"petalWidth":1.5,"species":"versicolor"},{"sepalLength":6.9,"sepalWidth":3.1,"petalLength":4.9,"petalWidth":1.5,"species":"versicolor"},{"sepalLength":5.5,"sepalWidth":2.3,"petalLength":4,"petalWidth":1.3,"species":"versicolor"},{"sepalLength":6.5,"sepalWidth":2.8,"petalLength":4.6,"petalWidth":1.5,"species":"versicolor"},{"sepalLength":5.7,"sepalWidth":2.8,"petalLength":4.5,"petalWidth":1.3,"species":"versicolor"},{"sepalLength":6.3,"sepalWidth":3.3,"petalLength":4.7,"petalWidth":1.6,"species":"versicolor"},{"sepalLength":4.9,"sepalWidth":2.4,"petalLength":3.3,"petalWidth":1,"species":"versicolor"},{"sepalLength":6.6,"sepalWidth":2.9,"petalLength":4.6,"petalWidth":1.3,"species":"versicolor"},{"sepalLength":5.2,"sepalWidth":2.7,"petalLength":3.9,"petalWidth":1.4,"species":"versicolor"},{"sepalLength":6.3,"sepalWidth":3.3,"petalLength":6,"petalWidth":2.5,"species":"virginica"},{"sepalLength":5.8,"sepalWidth":2.7,"petalLength":5.1,"petalWidth":1.9,"species":"virginica"},{"sepalLength":7.1,"sepalWidth":3,"petalLength":5.9,"petalWidth":2.1,"species":"virginica"},{"sepalLength":6.3,"sepalWidth":2.9,"petalLength":5.6,"petalWidth":1.8,"species":"virginica"},{"sepalLength":6.5,"sepalWidth":3,"petalLength":5.8,"petalWidth":2.2,"species":"virginica"},{"sepalLength":7.6,"sepalWidth":3,"petalLength":6.6,"petalWidth":2.1,"species":"virginica"},{"sepalLength":4.9,"sepalWidth":2.5,"petalLength":4.5,"petalWidth":1.7,"species":"virginica"},{"sepalLength":7.3,"sepalWidth":2.9,"petalLength":6.3,"petalWidth":1.8,"species":"virginica"},{"sepalLength":6.7,"sepalWidth":2.5,"petalLength":5.8,"petalWidth":1.8,"species":"virginica"},{"sepalLength":7.2,"sepalWidth":3.6,"petalLength":6.1,"petalWidth":2.5,"species":"virginica"}]

2.5.2. Pretty Printing JSON

$ URL='https://raw.githubusercontent.com/AstroMatt/book-python/master/serialization/data/iris.json'
$ curl $URL |python -m json.tool
[
    {
        "petalLength": 1.4,
        "petalWidth": 0.2,
        "sepalLength": 5.1,
        "sepalWidth": 3.5,
        "species": "setosa"
    },
    {
        "petalLength": 1.4,
        "petalWidth": 0.2,
        "sepalLength": 4.9,
        "sepalWidth": 3,
        "species": "setosa"
    },
    {
        "petalLength": 1.3,
        "petalWidth": 0.2,
        "sepalLength": 4.7,
        "sepalWidth": 3.2,
        "species": "setosa"
    },
...

2.5.3. Check JSON Syntax

$ echo '{"sepalLength":5.1,"sepalWidth":3.5,}' | python -m json.tool
Expecting property name enclosed in double quotes: line 1 column 37 (char 36)

2.6. Assignments

2.6.1. Serialize

Listing 220. Iris Serialize
DATA = [
    ('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'),
    (4.9, 2.5, 4.5, 1.7, 'virginica'),
    (7.1, 3.0, 5.9, 2.1, 'virginica'),
    (4.6, 3.4, 1.4, 0.3, 'setosa'),
    (5.4, 3.9, 1.7, 0.4, 'setosa'),
    (5.7, 2.8, 4.5, 1.3, 'versicolor'),
    (5.0, 3.6, 1.4, 0.3, 'setosa'),
    (5.5, 2.3, 4.0, 1.3, 'versicolor'),
    (6.5, 3.0, 5.8, 2.2, 'virginica'),
    (6.5, 2.8, 4.6, 1.5, 'versicolor'),
    (6.3, 3.3, 6.0, 2.5, 'virginica'),
    (6.9, 3.1, 4.9, 1.5, 'versicolor'),
    (4.6, 3.1, 1.5, 0.2, 'setosa'),
]
  1. Z danych wydziel nagłówek i pomiary

  2. Wygeneruj List[dict]

    • klucz: nazwa z nagłówka

    • wartość: wyniki pomiarów lub gatunek

  3. Słownik wynikowy ma wyglądać następująco:

    [
        {'Sepal length': 5.8, 'Sepal width': 2.7, ...},
        {'Sepal length': 5.1, 'Sepal width': 3.5, ...},
        {'Sepal length': 5.7, 'Sepal width': 2.8, ...},
        ...
    ]
    
  4. Zapisz do pliku iris.json w formacie JSON

The whys and wherefores
  • Serializacja danych

  • Korzystanie z biblioteki JSON

  • Konwersja typów

  • Praca z plikami

2.6.2. Deserialize

  1. Dane z listingu poniżej skopiuj do pliku "iris.json"

    Listing 221. Iris dataset in JSON
    [{"sepalLength":5.1,"sepalWidth":3.5,"petalLength":1.4,"petalWidth":0.2,"species":"setosa"},{"sepalLength":4.9,"sepalWidth":3,"petalLength":1.4,"petalWidth":0.2,"species":"setosa"},{"sepalLength":4.7,"sepalWidth":3.2,"petalLength":1.3,"petalWidth":0.2,"species":"setosa"},{"sepalLength":4.6,"sepalWidth":3.1,"petalLength":1.5,"petalWidth":0.2,"species":"setosa"},{"sepalLength":5,"sepalWidth":3.6,"petalLength":1.4,"petalWidth":0.2,"species":"setosa"},{"sepalLength":5.4,"sepalWidth":3.9,"petalLength":1.7,"petalWidth":0.4,"species":"setosa"},{"sepalLength":4.6,"sepalWidth":3.4,"petalLength":1.4,"petalWidth":0.3,"species":"setosa"},{"sepalLength":5,"sepalWidth":3.4,"petalLength":1.5,"petalWidth":0.2,"species":"setosa"},{"sepalLength":4.4,"sepalWidth":2.9,"petalLength":1.4,"petalWidth":0.2,"species":"setosa"},{"sepalLength":4.9,"sepalWidth":3.1,"petalLength":1.5,"petalWidth":0.1,"species":"setosa"},{"sepalLength":7,"sepalWidth":3.2,"petalLength":4.7,"petalWidth":1.4,"species":"versicolor"},{"sepalLength":6.4,"sepalWidth":3.2,"petalLength":4.5,"petalWidth":1.5,"species":"versicolor"},{"sepalLength":6.9,"sepalWidth":3.1,"petalLength":4.9,"petalWidth":1.5,"species":"versicolor"},{"sepalLength":5.5,"sepalWidth":2.3,"petalLength":4,"petalWidth":1.3,"species":"versicolor"},{"sepalLength":6.5,"sepalWidth":2.8,"petalLength":4.6,"petalWidth":1.5,"species":"versicolor"},{"sepalLength":5.7,"sepalWidth":2.8,"petalLength":4.5,"petalWidth":1.3,"species":"versicolor"},{"sepalLength":6.3,"sepalWidth":3.3,"petalLength":4.7,"petalWidth":1.6,"species":"versicolor"},{"sepalLength":4.9,"sepalWidth":2.4,"petalLength":3.3,"petalWidth":1,"species":"versicolor"},{"sepalLength":6.6,"sepalWidth":2.9,"petalLength":4.6,"petalWidth":1.3,"species":"versicolor"},{"sepalLength":5.2,"sepalWidth":2.7,"petalLength":3.9,"petalWidth":1.4,"species":"versicolor"},{"sepalLength":6.3,"sepalWidth":3.3,"petalLength":6,"petalWidth":2.5,"species":"virginica"},{"sepalLength":5.8,"sepalWidth":2.7,"petalLength":5.1,"petalWidth":1.9,"species":"virginica"},{"sepalLength":7.1,"sepalWidth":3,"petalLength":5.9,"petalWidth":2.1,"species":"virginica"},{"sepalLength":6.3,"sepalWidth":2.9,"petalLength":5.6,"petalWidth":1.8,"species":"virginica"},{"sepalLength":6.5,"sepalWidth":3,"petalLength":5.8,"petalWidth":2.2,"species":"virginica"},{"sepalLength":7.6,"sepalWidth":3,"petalLength":6.6,"petalWidth":2.1,"species":"virginica"},{"sepalLength":4.9,"sepalWidth":2.5,"petalLength":4.5,"petalWidth":1.7,"species":"virginica"},{"sepalLength":7.3,"sepalWidth":2.9,"petalLength":6.3,"petalWidth":1.8,"species":"virginica"},{"sepalLength":6.7,"sepalWidth":2.5,"petalLength":5.8,"petalWidth":1.8,"species":"virginica"},{"sepalLength":7.2,"sepalWidth":3.6,"petalLength":6.1,"petalWidth":2.5,"species":"virginica"}]
    
  2. Odczytaj dane z pliku, i wyświetl je w formacie List[tuple]

  3. Pierwsza linijka ma zawierać nagłówek

  4. Kolejne linie mają mieć dane

The whys and wherefores
  • Deserializacja danych

  • Korzystanie z biblioteki JSON

  • Konwersja typów

  • Praca z plikami

2.6.3. Serializing datetime

Listing 222. Sample Python data JSON
from datetime import datetime, date


DATA = {
    "astronaut": {
        "date": date(1961, 4, 12),
        "person": "[email protected]"
    },
    "flight": [
        {"datetime": datetime(1969, 7, 21, 2, 56, 15), "action": "landing"}
    ]
}
  1. Skopiuj do swojego pliku strukturę danych Listing 222.

  2. Zapisz ją do pliku JSON

  3. Wczytaj ją z pliku JSON jako obiekty Pythona (ten sam efekt co na listingu)

The whys and wherefores
  • Serializacja danych

  • Korzystanie z biblioteki JSON

  • Serializowanie zagnieżdżonych dat i dat z czasem

2.6.4. Serializing objects

  • Complexity level: medium

  • Lines of code to write: 15 lines

  • Estimated time of completion: 20 min

  • Filename: solution/json_object.py

Listing 223. Sample Python data JSON
DATA = [
  {"sepalLength": 5.0, "sepalWidth": 3.6, "petalLength": 1.4, "petalWidth": 0.2, "species": "setosa"},
  {"sepalLength": 4.9, "sepalWidth": 3.1, "petalLength": 1.5, "petalWidth": 0.1, "species": "setosa"},
  {"sepalLength": 4.9, "sepalWidth": 3.0, "petalLength": 1.4, "petalWidth": 0.2, "species": "setosa"},
  {"sepalLength": 7.0, "sepalWidth": 3.2, "petalLength": 4.7, "petalWidth": 1.4, "species": "versicolor"},
  {"sepalLength": 4.6, "sepalWidth": 3.1, "petalLength": 1.5, "petalWidth": 0.2, "species": "setosa"},
  {"sepalLength": 6.5, "sepalWidth": 3.0, "petalLength": 5.8, "petalWidth": 2.2, "species": "virginica"},
  {"sepalLength": 7.1, "sepalWidth": 3.0, "petalLength": 5.9, "petalWidth": 2.1, "species": "virginica"},
  {"sepalLength": 6.7, "sepalWidth": 2.5, "petalLength": 5.8, "petalWidth": 1.8, "species": "virginica"},
  {"sepalLength": 5.2, "sepalWidth": 2.7, "petalLength": 3.9, "petalWidth": 1.4, "species": "versicolor"},
  {"sepalLength": 5.0, "sepalWidth": 3.4, "petalLength": 1.5, "petalWidth": 0.2, "species": "setosa"},
  {"sepalLength": 4.9, "sepalWidth": 2.4, "petalLength": 3.3, "petalWidth": 1.0, "species": "versicolor"},
  {"sepalLength": 6.5, "sepalWidth": 2.8, "petalLength": 4.6, "petalWidth": 1.5, "species": "versicolor"},
  {"sepalLength": 5.4, "sepalWidth": 3.9, "petalLength": 1.7, "petalWidth": 0.4, "species": "setosa"},
  {"sepalLength": 6.3, "sepalWidth": 3.3, "petalLength": 4.7, "petalWidth": 1.6, "species": "versicolor"},
  {"sepalLength": 6.4, "sepalWidth": 3.2, "petalLength": 4.5, "petalWidth": 1.5, "species": "versicolor"},
  {"sepalLength": 6.6, "sepalWidth": 2.9, "petalLength": 4.6, "petalWidth": 1.3, "species": "versicolor"},
  {"sepalLength": 5.8, "sepalWidth": 2.7, "petalLength": 5.1, "petalWidth": 1.9, "species": "virginica"},
  {"sepalLength": 6.3, "sepalWidth": 2.9, "petalLength": 5.6, "petalWidth": 1.8, "species": "virginica"},
  {"sepalLength": 7.6, "sepalWidth": 3.0, "petalLength": 6.6, "petalWidth": 2.1, "species": "virginica"},
  {"sepalLength": 5.1, "sepalWidth": 3.5, "petalLength": 1.4, "petalWidth": 0.2, "species": "setosa"},
  {"sepalLength": 7.3, "sepalWidth": 2.9, "petalLength": 6.3, "petalWidth": 1.8, "species": "virginica"},
  {"sepalLength": 4.7, "sepalWidth": 3.2, "petalLength": 1.3, "petalWidth": 0.2, "species": "setosa"},
  {"sepalLength": 6.9, "sepalWidth": 3.1, "petalLength": 4.9, "petalWidth": 1.5, "species": "versicolor"},
  {"sepalLength": 7.2, "sepalWidth": 3.6, "petalLength": 6.1, "petalWidth": 2.5, "species": "virginica"},
  {"sepalLength": 4.4, "sepalWidth": 2.9, "petalLength": 1.4, "petalWidth": 0.2, "species": "setosa"},
  {"sepalLength": 5.5, "sepalWidth": 2.3, "petalLength": 4.0, "petalWidth": 1.3, "species": "versicolor"},
  {"sepalLength": 4.6, "sepalWidth": 3.4, "petalLength": 1.4, "petalWidth": 0.3, "species": "setosa"},
  {"sepalLength": 6.3, "sepalWidth": 3.3, "petalLength": 6.0, "petalWidth": 2.5, "species": "virginica"},
  {"sepalLength": 4.9, "sepalWidth": 2.5, "petalLength": 4.5, "petalWidth": 1.7, "species": "virginica"},
  {"sepalLength": 5.7, "sepalWidth": 2.8, "petalLength": 4.5, "petalWidth": 1.3, "species": "versicolor"}
]
  1. Skopiuj do pliku iris.json dane z listingu Listing 223.

  2. Stwórz klasy Setosa, Virginica, Versicolor

  3. Czytając dane z pliku twórz obiekty powyższych klas w zależności od wyniku pomiaru (pole "species")

The whys and wherefores
  • Serializacja danych

  • Korzystanie z biblioteki JSON

  • Serializowanie zagnieżdżonych obiektów

2.6.5. Deserialize data from GITHub

  • Complexity level: medium

  • Lines of code to write: 15 lines

  • Estimated time of completion: 20 min

  • Filename: solution/json_github.py

  1. Za pomocą biblioteki requests pobierz dane z https://api.github.com/users

  2. Iterując po rekordach twórz obiekty klasy User

The whys and wherefores
  • Deserializacja danych

  • Korzystanie z biblioteki JSON

  • Deserializacja zagnieżdżonych obiektów

  • Reprezentacja klas na podstawie danych otrzymanych przez API

2.6.6. Deserialize data from API

  • Complexity level: easy

  • Lines of code to write: 30 lines

  • Estimated time of completion: 30 min

  • Filename: solution/json_api.py

  1. Po API dostajesz JSONa tak jak na listingu poniżej

  2. Iterując po rekordach twórz obiekty klasy Astronaut

  3. Sparsuj user_permissions i przedstaw je za pomocą listy klas

  4. Nazwa klasy to klucz w słowniku

  5. Są zawsze cztery pola: "add", "modify", "view", "delete"

  6. Jeżeli jakieś pole jest wymienione, to ma wartość True, jeżeli nie to False

The whys and wherefores
  • Deserializacja danych

  • Korzystanie z biblioteki JSON

  • Deserializacja zagnieżdżonych obiektów

  • Reprezentacja klas na podstawie danych otrzymanych przez API

[{"model":"authorization.user","pk":1,"fields":{"password":"pbkdf2_sha256$120000$gvEBNiCeTrYa0$5C+NiCeTrYsha1PHogqvXNiCeTrY0CRSLYYAA90=","last_login":"1970-01-01T00:00:00.000Z","is_superuser":false,"username":"commander","first_name":"Иван","last_name":"Иванович","email":"","is_staff":true,"is_active":true,"date_joined":"1970-01-01T00:00:00.000Z","groups":[1],"user_permissions":[{"eclss":["add","modify","view"]},{"communication":["add","modify","view"]},{"medical":["add","modify","view"]},{"science":["add","modify","view"]}]}},{"model":"authorization.user","pk":2,"fields":{"password":"pbkdf2_sha256$120000$eUNiCeTrYHoh$X32NiCeTrYZOWFdBcVT1l3NiCeTrY4WJVhr+cKg=","last_login":null,"is_superuser":false,"username":"executive-officer","first_name":"José","last_name":"Jiménez","email":"","is_staff":true,"is_active":true,"date_joined":"1970-01-01T00:00:00.000Z","groups":[1],"user_permissions":[{"eclss":["add","modify","view"]},{"communication":["add","modify","view"]},{"medical":["add","modify","view"]},{"science":["add","modify","view"]}]}},{"model":"authorization.user","pk":3,"fields":{"password":"pbkdf2_sha256$120000$3G0RNiCeTrYlaV1$mVb62WNiCeTrYQ9aYzTsSh74NiCeTrY2+c9/M=","last_login":"1970-01-01T00:00:00.000Z","is_superuser":false,"username":"crew-medical-officer","first_name":"Melissa","last_name":"Lewis","email":"","is_staff":true,"is_active":true,"date_joined":"1970-01-01T00:00:00.000Z","groups":[1],"user_permissions":[{"communication":["add","view"]},{"medical":["add","modify","view"]},{"science":["add","modify","view"]}]}},{"model":"authorization.user","pk":4,"fields":{"password":"pbkdf2_sha256$120000$QmSNiCeTrYBv$Nt1jhVyacNiCeTrYSuKzJ//WdyjlNiCeTrYYZ3sB1r0g=","last_login":null,"is_superuser":false,"username":"science-data-officer","first_name":"Mark","last_name":"Watney","email":"","is_staff":true,"is_active":true,"date_joined":"1970-01-01T00:00:00.000Z","groups":[1],"user_permissions":[{"communication":["add","view"]},{"science":["add","modify","view"]}]}},{"model":"authorization.user","pk":5,"fields":{"password":"pbkdf2_sha256$120000$bxS4dNiCeTrY1n$Y8NiCeTrYRMa5bNJhTFjNiCeTrYp5swZni2RQbs=","last_login":null,"is_superuser":false,"username":"communication-officer","first_name":"Jan","last_name":"Twardowski","email":"","is_staff":true,"is_active":true,"date_joined":"1970-01-01T00:00:00.000Z","groups":[1],"user_permissions":[{"communication":["add","modify","view"]},{"science":["add","modify","view"]}]}},{"model":"authorization.user","pk":6,"fields":{"password":"pbkdf2_sha256$120000$aXNiCeTrY$UfCJrBh/qhXohNiCeTrYH8nsdANiCeTrYnShs9M/c=","last_login":null,"is_superuser":false,"username":"eclss-officer","first_name":"Harry","last_name":"Stamper","email":"","is_staff":true,"is_active":true,"date_joined":"1970-01-01T00:00:00.000Z","groups":[1],"user_permissions":[{"communication":["add","view"]},{"eclss":["add","modify","view"]},{"science":["add","modify","view"]}]}}]