Search code examples
pythonjsonmarshmallow

How can I use marshmallow to export a complex object to valid json (with double quotes)?


I have this simple code that uses marshmallow to convert complex object into its json representation:

from marshmallow import Schema, fields
import json


class Purchase:
    def __init__(self):
        self.date = ""
        self.item = ""
        self.price = ""
        self.description = ""


class User:
    def __init__(self):
        self.first_name = ""
        self.last_name = ""
        self.username = ""
        self.password = ""
        self.credit_card = ""
        self.purchase_history = list()


class PurchaseSchema(Schema):
    date = fields.Str()
    item = fields.Str()
    price = fields.Str()
    description = fields.Str()


class UsersSchema(Schema):
    first_name = fields.Str()
    last_name = fields.Str()
    username = fields.Str()
    password = fields.Str()
    credit_card = fields.Str()
    purchase_history = fields.List(fields.Nested(PurchaseSchema))


user = User()
for i in range(10):
    p = Purchase()
    if i % 2 == 0:
        p.item = "item \"" + str(i) + "\""
    else:
        p.item = "item \'" + str(i) + "\'"
    user.purchase_history.append(p)

schema = UsersSchema()
output = str(schema.dump(user))
print(output)

Unfortunately, the output is not exactly valid, since some of the strings start and end with single quotes instead of double quotes.

{
    'purchase_history': [{
        'price': '',
        'item': 'item "0"',
        'description': '',
        'date': ''
    }, {
        'price': '',
        'item': "item '1'",
        'description': '',
        'date': ''
    }, {
        'price': '',
        'item': 'item "2"',
        'description': '',
        'date': ''
    }, {
        'price': '',
        'item': "item '3'",
        'description': '',
        'date': ''
    }, {
        'price': '',
        'item': 'item "4"',
        'description': '',
        'date': ''
    }, {
        'price': '',
        'item': "item '5'",
        'description': '',
        'date': ''
    }, {
        'price': '',
        'item': 'item "6"',
        'description': '',
        'date': ''
    }, {
        'price': '',
        'item': "item '7'",
        'description': '',
        'date': ''
    }, {
        'price': '',
        'item': 'item "8"',
        'description': '',
        'date': ''
    }, {
        'price': '',
        'item': "item '9'",
        'description': '',
        'date': ''
    }],
    'first_name': '',
    'last_name': '',
    'credit_card': '',
    'password': '',
    'username': ''
}

As a result, if I add parsed = json.load(output) to the end of the script I get an error:

json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

How can I use marshmallow to export the schema to valid JSON? (with double quotes)


Solution

  • schema.dump returns a dict, so str gives you something like a Python literal.

    You can encode the dict with json.dumps:

    schema = UsersSchema()
    output = schema.dump(user)
    print(json.dumps(output))
    

    or use schema.dumps to go directly to JSON.

    schema = UsersSchema()
    output = schema.dumps(user)
    print(output)