I have a REST API endpoint in which I need to parse incoming nested JSON of the format:
site: {
id: '37251',
site_name: 'TestSite',
address: {
'address': '1234 Blaisdell Ave',
'city': 'Minneapolis',
'state': 'MN',
'zip': '55456',
'neighborhood': 'Kingfield',
'county': 'Hennepin',
},
geolocation: {
latitude : '41.6544',
longitude : '73.3322',
accuracy: '45'
}
}
into the following SQLAlchemy classes:
Site:
class Site(db.Model):
__tablename__ = 'site'
id = Column(Integer, primary_key=True, autoincrement=True)
site_name = Column(String(80))# does site have a formal name
address_id = Column(Integer, ForeignKey('address.id'))
address = relationship("Address", backref=backref("site", uselist=False))
geoposition_id = Column(Integer, ForeignKey('geoposition.id'))
geoposition = relationship("Geoposition", backref=backref("site", uselist=False))
evaluations = relationship("Evaluation", backref="site")
site_maintainers = relationship("SiteMaintainer", backref="site")
Address (a Site has one Address):
class Address(db.Model):
__tablename__ = 'address'
id = Column(Integer, primary_key=True, autoincrement=True)
address = Column(String(80))
city = Column(String(80))
state = Column(String(2))
zip = Column(String(5))
neighborhood = Column(String(80))
county = Column(String(80))
and Geoposition (a Site has one Geoposition):
class Geoposition(db.Model):
__tablename__ = 'geoposition'
id = Column(Integer, primary_key=True, autoincrement=True)
site_id = Column(Integer)
latitude = Column(Float(20))
longitude = Column(Float(20))
accuracy = Column(Float(20))
timestamp = Column(DateTime)
Getting the SQLAlchemey data into JSON is easy, but I need to parse the JSON from my request so that I can append/update data that is sent via POST to the RESTful API. I know how to handle non-nested JSON, but I will be the first to admit that I am clueless in dealing with the nested JSON for records that belong to multiple tables in a relational structure.
I've tried searching high and low for this without any luck. Closest I could find is here "Nested validation with the flask-restful RequestParser", but this is not clicking for what I need to do based on my nested structure.
Cool! Looks like Flask handles this through the request handler:
With this JSON:
site: {
"id": "37251",
"site_name": "TestSite",
"address": {
"address": "1234 Blaisdell Ave",
"city": "Minneapolis",
"state": "MN",
"zip": "55456",
"neighborhood": "Kingfield",
"county": "Hennepin"
},
geolocation: {
latitude : "41.6544",
longitude : "73.3322",
accuracy: "45"
}
}
Sent to this endpoint:
@app.route('/api/resource', methods=['GET','POST','OPTIONS'])
@cross_origin() # allow all origins all methods
@auth.login_required
def get_resource():
# Get the parsed contents of the form data
json = request.json
print(json)
# Render template
return jsonify(json)
I get the following object:
{u'site': {u'geolocation': {u'latitude': u'41.6544', u'longitude': u'73.3322', u'accuracy': u'45'}, u'site_name': u'TestSite', u'id': u'37251', u'address': {u'city': u'Minneapolis', u'neighborhood': u'Kingfield', u'zip': u'55456', u'county': u'Hennepin', u'state': u'MN', u'address': u'1234 Blaisdell Ave'}}}
UPDATE:
Am able to access all my dictionary items just fine using this code for a test in my endpoint:
# print entire object
print json['site']
# define dictionary item for entire object
site = json['site']
print site["site_name"]
# print address object
print site['address']
# define address dictionary object
address = json['site']['address']
print address["address"]
# define geolocation dictionary object
geolocation = json['site']['geolocation']
print geolocation["accuracy"]
In retrospect, this seems rather trivial now. I hope this helps someone in the future.
Do you have access and can edit the JSON?
A few edits would help make it a valid JSON:
{
and }
,
in the country
lineIf you can do so, you JSON will look like this:
{
"site": {
"id": "37251",
"site_name": "TestSite",
"address": {
"address": "1234BlaisdellAve",
"city": "Minneapolis",
"state": "MN",
"zip": "55456",
"neighborhood": "Kingfield",
"county": "Hennepin"
},
"geolocation": {
"latitude": "41.6544",
"longitude": "73.3322",
"accuracy": "45"
}
}
}
Sorting that out, use Python's json
to deal with it:
import json
file_handler = open('test.json', 'r')
parsed_data = json.loads(file_handler.read())
print parsed_data
The output is a diciotnary that you can easily iterate with to validate your data:
{u'site': {u'geolocation': {u'latitude': u'41.6544', u'longitude': u'73.3322', u'accuracy': u'45'}, u'site_name': u'TestSite', u'id': u'37251', u'address': {u'city': u'Minneapolis', u'neighborhood': u'Kingfield', u'zip': u'55456', u'county': u'Hennepin', u'state': u'MN', u'address': u'1234BlaisdellAve'}}}
But if you can't edit your JSON to make its syntax better, json.loads
would not parse it…
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With