How to make a class JSON serializable
Do you have an idea about the expected output? For example, will this do?
>>> f = FileItem("/foo/bar")
>>> magic(f)
'{"fname": "/foo/bar"}'
In that case you can merely call json.dumps(f.__dict__)
.
If you want more customized output then you will have to subclass JSONEncoder
and implement your own custom serialization.
For a trivial example, see below.
>>> from json import JSONEncoder
>>> class MyEncoder(JSONEncoder):
def default(self, o):
return o.__dict__
>>> MyEncoder().encode(f)
'{"fname": "/foo/bar"}'
Then you pass this class into the json.dumps()
method as cls
kwarg:
json.dumps(cls=MyEncoder)
If you also want to decode then you'll have to supply a custom object_hook
to the JSONDecoder
class. For example:
>>> def from_json(json_object):
if 'fname' in json_object:
return FileItem(json_object['fname'])
>>> f = JSONDecoder(object_hook = from_json).decode('{"fname": "/foo/bar"}')
>>> f
<__main__.FileItem object at 0x9337fac>
>>>
Serializing class instance to JSON
The basic problem is that the JSON encoder json.dumps()
only knows how to serialize a limited set of object types by default, all built-in types. List here: https://docs.python.org/3.3/library/json.html#encoders-and-decoders
One good solution would be to make your class inherit from JSONEncoder
and then implement the JSONEncoder.default()
function, and make that function emit the correct JSON for your class.
A simple solution would be to call json.dumps()
on the .__dict__
member of that instance. That is a standard Python dict
and if your class is simple it will be JSON serializable.
class Foo(object):
def __init__(self):
self.x = 1
self.y = 2
foo = Foo()
s = json.dumps(foo) # raises TypeError with "is not JSON serializable"
s = json.dumps(foo.__dict__) # s set to: {"x":1, "y":2}
The above approach is discussed in this blog posting:
Serializing arbitrary Python objects to JSON using _dict_
And, of course, Python offers a built-in function that accesses .__dict__
for you, called vars()
.
So the above example can also be done as:
s = json.dumps(vars(foo)) # s set to: {"x":1, "y":2}
Serializing an ES6 class object as JSON
As with any other object you want to stringify in JS, you can use JSON.stringify
:
JSON.stringify(yourObject);
class MyClass { constructor() { this.foo = 3 }}
var myClass = new MyClass()
console.log(JSON.stringify(myClass));
Python: converting class objects to JSON - object is not JSON serializable
You wish the encoder to support both Decimal
and dataclass
es. You can do it like so:
import dataclasses, json
class JSONEncoder(json.JSONEncoder):
def default(self, o):
if dataclasses.is_dataclass(o):
return dataclasses.asdict(o)
if isinstance(obj, Decimal):
return str(obj)
return super().default(o)
json.dumps(foo, cls=JSONEncoder)
Serializing a javascript class object?
You can use JSON.stringify
, but be aware that it only serialize properties, not methods. So to unserialize an object, just create a dummy instance and use Object.assign
to update the properties using the retrieved object:
function serialize(instance) {
var str = JSON.stringify(instance);
// save str or whatever
}
function unserialize(str, theClass) {
var instance = new theClass(); // NOTE: if your constructor checks for unpassed arguments, then just pass dummy ones to prevent throwing an error
var serializedObject = JSON.parse(str);
Object.assign(instance, serializedObject);
return instance;
}
Example:
function serialize(obj) { var str = JSON.stringify(obj); return str;}
function unserialize(str, theClass) { var instance = new theClass(); var serializedObject = JSON.parse(str); Object.assign(instance, serializedObject); return instance;}
// TEST CLASS
class TestClass { constructor(a, b) { this.a = a; this.b = b; }
sum() { return this.a + this.b; }}
// USAGE
var instance = new TestClass(5, 7);
var str = serialize(instance);
var retrievedInstance = unserialize(str, TestClass);
console.log(retrievedInstance.sum());
json serialization of a list of objects of a custom class
I've solved this by adding an encode()
method to the class:
def encode(self):
return self.__dict__
and adding some arguments to json.dumps:
jsontracks = json.dumps(tracklist, default=lambda o: o.encode(), indent=4)
This will "crawl" down your class tree (if you have any child classes) and encode every object as a json list/object automatically. This should work with just about any class and is fast to type. You may also want to control which class parameters get encoded with something like:
def encode(self):
return {'name': self.name,
'code': self.code,
'amount': self.amount,
'minimum': self.minimum,
'maximum': self.maximum}
or a little bit faster to edit (if you're lazy like me):
def encode(self):
encoded_items = ['name', 'code', 'batch_size', 'cost',
'unit', 'ingredients', 'nutrients']
return {k: v for k, v in self.__dict__.items() if k in encoded_items}
full code:
import json
class Song:
def __init__(self, sname, sartist, coverart, albname, albartist, spotid):
self.sname = sname
self.sartist = sartist
self.coverart = coverart
self.albname = albname
self.albartist = albartist
self.spotid = spotid
def encode(self):
return self.__dict__
tracklist = [
Song('Imagine', 'John Lennon', None, None, None, None),
Song('Hey Jude', 'The Beatles', None, None, None, None),
Song('(I Can\'t Get No) Satisfaction', 'The Rolling Stones', None, None, None, None),
]
jsontracks = json.dumps(tracklist, default=lambda o: o.encode(), indent=4)
print(jsontracks)
output:
[
{
"sname": "Imagine",
"sartist": "John Lennon",
"coverart": null,
"albname": null,
"albartist": null,
"spotid": null
},
{
"sname": "Hey Jude",
"sartist": "The Beatles",
"coverart": null,
"albname": null,
"albartist": null,
"spotid": null
},
{
"sname": "(I Can't Get No) Satisfaction",
"sartist": "The Rolling Stones",
"coverart": null,
"albname": null,
"albartist": null,
"spotid": null
}
]
How to serialize object to json with custom fields in python
IIUC, you could do the following:
import json
class Person(object):
def __init__(self, age, name, weight):
self.person_age = age
self.person_name = name
self.weight = weight
p = Person(30, 'Peter', 78)
mapping = {'person_age': 'age', 'person_name': 'name'}
result = json.dumps({mapping.get(k, k): v for k, v in p.__dict__.items()})
print(result)
Output
{"age": 30, "name": "Peter", "weight": 78}
Note that you only need those names you want to change, in the example above weight
remains unchanged.
Serialize Python object in another object with json?
One option is to convert any existing classes into dataclasses, which are just normal classes with some autogenerated methods like __init__
and __repr__
for example.
Then, you can recursively serialize a nested dataclass model using the asdict
helper function that dataclasses
provides:
from dataclasses import dataclass, asdict
@dataclass
class Person:
name: str
address: 'Address'
@dataclass
class Address:
country: str
city: str
add = Address("USA", "New York")
person = Person("John", add)
serialized = asdict(person)
print(serialized)
# {'name': 'John', 'address': {'country': 'USA', 'city': 'New York'}}
If you need to work with more complex types like datetime
, or else need to load or de-serialize json to a dataclass model, I would check out a de/serialization library like the dataclass-wizard, which can help further simplify this process:
from dataclasses import dataclass
from datetime import date
from dataclass_wizard import fromdict, asdict
@dataclass
class Person:
name: str
address: 'Address'
birth_date: date
@dataclass
class Address:
country: str
city: str
person = fromdict(Person, {'name': 'John', 'BirthDate': '1990-01-01', 'address': {'country': 'USA', 'city': 'New York'}})
print(person)
# Person(name='John', address=Address(country='USA', city='New York'), birth_date=datetime.date(1990, 1, 1))
serialized = asdict(person)
print(serialized)
# {'name': 'John', 'address': {'country': 'USA', 'city': 'New York'}, 'birthDate': '1990-01-01'}
Related Topics
Using Logging in Multiple Modules
Serializing Class Instance to JSON
Tkinter: Binding Mousewheel to Scrollbar
How to Print a Generator Expression
How Might I Remove Duplicate Lines from a File
Add a String Prefix to Each Value in a String Column Using Pandas
What Does the Percentage Sign Mean in Python
Trying to Mock Datetime.Date.Today(), But Not Working
String Concatenation Without '+' Operator
Adding Directory to Sys.Path /Pythonpath
How to Solve a Pair of Nonlinear Equations Using Python
Python Iterator Is Empty After Performing Some Action on It
Calling Filter Returns <Filter Object at ... >
How to Build Multiple Submit Buttons Django Form