Brian Brown
Brian Brown

Reputation: 4311

Convert class object into Json (with datetime field) - TypeError: Object of type datetime is not JSON serializable

I'm trying to convert object into JSON. Converting from JSON to object was simple. When I try to use the dumps method, I'm getting the error: TypeError: Object of type datetime is not JSON serializable. Is this possible to convert such class?

import json
import datetime
from types import SimpleNamespace


class Outcome:

    def __init__(self, name='', date=datetime.datetime.now(), price=0.0):
        self.name = name
        self.date = datetime.datetime.strptime(date, '%Y-%m-%d')
        self.price = float(price)

# convert from json to outcome
txt = b'{"name": "milk", "date": "2020-01-02", "price": 1.99}'
txt = txt.decode("utf-8")
x = json.loads(txt, object_hook=lambda d: SimpleNamespace(**d))
o = Outcome(x.name, x.date, x.price)
print(o.name, o.date, o.price)

# convert outcome to json (how?)
o2 = json.dumps(o.__dict__)
print(o2.name, o2.date, o2.price)

Upvotes: 1

Views: 318

Answers (1)

bherbruck
bherbruck

Reputation: 2226

You can use check if the value is a date with isinstance(v, datetime.date):

import json
import datetime
from types import SimpleNamespace


class Outcome:
    def __init__(self, name='', date=datetime.datetime.now(), price=0.0):
        self.name = name
        self.date = datetime.datetime.strptime(date, '%Y-%m-%d')
        self.price = float(price)

# convert from json to outcome
txt = b'{"name": "milk", "date": "2020-01-02", "price": 1.99}'
txt = txt.decode("utf-8")
x = json.loads(txt, object_hook=lambda d: SimpleNamespace(**d))
o = Outcome(x.name, x.date, x.price)
print(o.name, o.date, o.price)

# dict comprehension to check if each value is a date
o2 = json.dumps({k: v.isoformat() if isinstance(v, datetime.date) else v
                 for k, v in o.__dict__.items()})

print(o2)

Output:

milk 2020-01-02 00:00:00 1.99
{"name": "milk", "date": "2020-01-02T00:00:00", "price": 1.99}

You can also make an encode() and decode() method in your class to customize the saving and loading of your class to json and use that instead of the lambda fo object_hook

Upvotes: 1

Related Questions