Serializing Class Instance to JSON

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 dataclasses. 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



Leave a reply



Submit