I'm working with sqlite3 JSON1 extension in python3. The following code returns the output as string, but I'd like it to be a JSON object. Is this even possible in sqlite3 WITHOUT using json.loads()?
conn = sqlite3.connect(':memory:')
c = conn.cursor()
c.execute('''SELECT json_quote(json_object('a',2,'c',json_object('e',5))),
json_array(1,2,'3',4),
json_object('a',2,'c',json_object('e',5))
''')
row = c.fetchone()
col_a, col_b, col_c = row
print(row)
print(type(col_a), type(col_b), type(col_c))
Output
('{"a":2,"c":{"e":5}}', '[1,2,"3",4]', '{"a":2,"c":{"e":5}}')
<class 'str'> <class 'str'> <class 'str'>
It would be better if I can get it to work via SQLalchemy (again, I would like to avoid using json.loads())
from sqlalchemy import create_engine, Column, String, MetaData, Table, JSON
from sqlalchemy.orm import mapper
from sqlalchemy.sql import text
engine = create_engine('sqlite:///:memory:', echo=True)
metadata = MetaData(bind=engine)
table = Table('device', metadata, Column('id', String, primary_key=True), Column('properties', JSON))
table.create()
properties = {'id': 'id1', 'device_name': 'device1', 'role': 'backbone', 'in_maint': True}
table.insert().values(id=properties['id'], properties=properties).execute()
class SqliteTable(object):
pass
mapper(SqliteTable, table)
sql_string = '''SELECT json_extract(device.properties, '$') AS properties
FROM device'''
sql_params = {}
with engine.connect() as connection:
rows = connection.execute(text(sql_string), **sql_params).fetchall()
results = [{k: v for k, v in row.items()} for row in rows]
print(results)
engine.dispose()
The properties value is a string and not a JSON object.
[{'properties': '{"id":"id1","device_name":"device1","role":"backbone","in_maint":true}'}]
EDIT: I do not know upfront which columns returned will have JSON data in them, and therefore, the need to do this without performing a json.loads() on each column's value. Ultimately, this data will be returned back to the user in JSON. The API users will be executing raw SQL queries.