I have two ways to represent Python object by json.dumps()
First:
person = {
"name": "John",
"age": 30,
"city": "New York"
}
Second:
class Person:
def _init_(self, name, age, city):
self.name = name
self.age = age
self.city = city
person = Person("John", 30, "New York")
Then I tried p1 = json.dumps(person), the second way would say it's not JSON serializable.
So basically for Python, json.dumps only work for built-in object like dict object?
If you are asking about vanilla Python, serialization could be done this way:
import json
class Person:
def __init__(self, name, age, city):
self.name = name
self.age = age
self.city = city
def to_json(self):
return json.dumps(self, default=lambda o: o.__dict__)
person = Person("John", 30, "New York")
print(person.to_json())
So we're just converting an object to a dict using __dict__ attribute.
But if you need something more sophisticated, you might need DRF (Django REST Framework) or pydantic. An example how it could be done with DRF:
from rest_framework import serializers
from rest_framework.serializers import Serializer
class Person:
def __init__(self, name, age, city):
self.name = name
self.age = age
self.city = city
class PersonSerializer(Serializer):
name = serializers.CharField()
age = serializers.IntegerField()
city = serializers.CharField()
def create(self, validated_data):
return Person(**validated_data)
person = Person("John", 30, "New York")
print(PersonSerializer(person).data)
This way you have a much better control over it. See docs.
Yes, the json module only knows how to serialize certain built-in types. An easy way to work with classes that have "fields" is the dataclasses module.
Example:
from dataclasses import dataclass, asdict
import json
@dataclass
class Person:
name: str
age: int
city: str
person = Person("John", 30, "New York")
print(json.dumps(asdict(person)))
The asdict() function converts the dataclass instance into a dict which json can serialize.
With Python 3.6+ you can use dataclasses in Python along with the asdict helper function to convert a dataclass instance to a Python dict object.
Note: For 3.6, you'll need a backport for the
dataclassesmodule, as it only became a builtin to Python starting in 3.7.
import json
from dataclasses import dataclass, asdict
@dataclass
class Person:
name: str
age: int
city: str
person = Person("John", 30, "New York")
person_dict = asdict(person)
json_string = json.dumps(person_dict, indent=2)
print(json_string)
Out:
{
"name": "John",
"age": 30,
"city": "New York"
}
If you have a more complex use case, or end up with needing to (de)serialize a nested dataclass model, I'd check out an external library like the dataclass-wizard that supports such a use case in particular.