'Python Flask, sqlalchemy and marshmallow serialization Issue in JSON representation and DB mirroring structure

Writing a REST API with Flask - I have declared 2 simple Models (Company and Address) using SQLAlchemy and i have also created the underlying DB and Tables in PostgreSQL (running Locally on PGAdmin).

Here the Models with (repr andjson methods included):

import os
import json
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
app = Flask(__name__)
app.config.from_object(os.environ['APP_SETTINGS'])
db = SQLAlchemy(app)
ma = Marshmallow(app)



#MODELS
class Company(db.Model):
__tablename__ = 'company'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
description = db.Column(db.String, nullable=False)
website = db.Column(db.Text, nullable=False)
addresses = db.relationship('Address', backref='company')

def json(self):
    return {'id': self.id,'description': self.description, 'website': self.website}

def __repr__(self):
    company_object = {
        'id': self.id,
        'description': self.description,
        'website': self.website,
        'addresses': self.addresses
    }
    return json.dumps(company_object)


def get_company(_id):
    return Company.json(Company.query.filter_by(id=_id).first())



class Address(db.Model):
__tablename__ = 'address'

id = db.Column(db.Integer, primary_key=True, autoincrement=True)
street = db.Column(db.String, nullable=False)
postcode = db.Column(db.String, nullable=False)
country = db.Column(db.String, nullable=False)
company_Id = db.Column(db.Integer,db.ForeignKey('company.id'))

def json(self):
    return {'id': self.id, 'street': self.street, 'postcode':self.postcode, 'country':self.country}

def __repr__(self):
    Address_object = {
        'id': self.id,
        'street': self.street, 
        'postcode':self.postcode, 
        'country':self.country
        }
    return json.dumps(Address_object)

Here is the Controller for the Compnay API ( a simple get company via id that should return a company with an array of object addresses nested inside ) a company can have one or more addresses) notice i have tried to implement the marshmallow schema Serialization ( i think i did something worng there- not really sure):

from models.company_model import Company,Address
import json
from marshmallow import Schema, fields
#This below import ma from database.py --> from flask_marshmallow import Marshmallow
from database import  ma
producstAPI = Blueprint('companyAPI', __name__)

class AddressSchema(ma.Schema):
    id = fields.Int(dump_only=True)
    street = fields.String()
    postcode = fields.String()
    country = fields.String()


class CompanySchema(ma.Schema):
        id = fields.Int(dump_only=True)
        title = fields.String()
        description = fields.String()
        imageURL = fields.String()
        addresses= fields.Nested(AddressSchema,many=True)

    

# GET A Compaany via id - this company ALREADY exists in the Postgresql db with id 1 in the table Company and so  the 2 addresses on the table Address
@companyAPI.route('/api/v1/companies/<int:company_id>')
def get_company_via_company_id(company_id):
    company = Company.get_company(company_id)
    company_schema = CompanySchema()
    output = company_schema.dump(company)
    return jsonify(output)

I start my Flask app and hit this URL 'http://127.0.0.1:5000/api/v1/companies/1' with POSTMAN to test my code. here Below is the result:

{
  "description": "My Company",
  id": 1,
  "price": 23.45,
  "addresses": [],
  "website": "A link"
}

But I am trying to acheive this format Below:

{
  "id": 1,
  "description": "My Company",
  "website": "A link",
  "addresses": [
    {
      "id": 1,
      "street": "1 dark street",
      "postcode": "00001",
      "country": "UK"
    },
    {
      "id": 1,
      "street": "1 light street",
      "postcode": "00002",
      "country": "Australia"
    }
  ]
}

I have some inexperience with more nested/complicated models declarations - i have worked with flat json structures and i never had issues like this before - or maybe the fact that creating 2 tables is the actuall isssue here? i have made 2 tables to maintain data integrity between the 2 object making sure every address is linked to a company - i tought that marshmallow would simplify things but it's becoming a bit of a nightmare. i believe this could be a simple Serialization issue. can someone help? also if i had to write in the DB via the api would i encoutner same issue?



Solution 1:[1]

It could be a typo in the question, but the fields should be named addresses, shouldn't it?

class CompanySchema(ma.Schema):
        id = fields.Int(dump_only=True)
        title = fields.String()
        description = fields.String()
        price = fields.Float()
        imageURL = fields.String()
        # Here:
        # sizeOptions = fields.Nested(AddressSchema,many=True)
        addresse = fields.Nested(AddressSchema,many=True)

There may be other issues because I don't see where price comes from.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jérôme