O Django possui uma boa serialização automática de modelos ORM retornados do DB para o formato JSON.
Como serializar o resultado da consulta SQLAlchemy para o formato JSON?
Eu tentei, jsonpickle.encode
mas ele codifica o próprio objeto de consulta. Eu tentei json.dumps(items)
mas volta
TypeError: <Product('3', 'some name', 'some desc')> is not JSON serializable
É realmente tão difícil serializar objetos SQLAlchemy ORM para JSON / XML? Não existe um serializador padrão para isso? Atualmente, é uma tarefa muito comum serializar resultados da consulta ORM.
O que eu preciso é apenas retornar a representação de dados JSON ou XML do resultado da consulta SQLAlchemy.
O resultado da consulta de objetos SQLAlchemy no formato JSON / XML é necessário para ser usado no datagird javascript (JQGrid http://www.trirand.com/blog/ )
python
json
sqlalchemy
Zelid
fonte
fonte
Respostas:
Uma implementação plana
Você poderia usar algo como isto:
e depois converta para JSON usando:
Ele ignorará os campos que não são codificáveis (defina-os como 'Nenhum').
Ele não expande automaticamente as relações (pois isso pode levar a referências próprias e fazer um loop para sempre).
Uma implementação recursiva e não circular
Se, no entanto, você preferir fazer um loop para sempre, use:
E então codifique objetos usando:
Isso codifica todos os filhos, todos os filhos e todos os filhos ... Codifica potencialmente todo o banco de dados inteiro, basicamente. Quando alcança algo que foi codificado antes, o codificará como 'Nenhum'.
Uma implementação seletiva recursiva, possivelmente circular
Outra alternativa, provavelmente melhor, é poder especificar os campos que você deseja expandir:
Agora você pode chamá-lo com:
Para expandir apenas os campos SQLAlchemy chamados 'pais', por exemplo.
fonte
online_order
eaddress
, ambos com um relacionamento comuser
, masonline_order
também tiver um relacionamento comaddress
. Se eu quisesse serializar tudo isso, teria que incluiraddress
nofields_to_expand
, mas não gostaria de serializar redundantementeaddress
devido ao seu relacionamento com ambosuser
eonline_order
.for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
para que ele leiafor field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata' and not x.startswith('query')]:
. Tenha em mente esta solução vai impedir que você tenha uma propriedade / relacionamento com 'consulta' o nomeVocê pode simplesmente enviar seu objeto como um dicionário:
E então você usa
User.as_dict()
para serializar seu objeto.Conforme explicado em Converter objeto de linha sqlalchemy em python dict
fonte
JSONEncoder
objeto. Você pode subclassificá-lo para definir seu próprio codificador para algum objeto, incluindo data e hora. Observe queFlask
, por exemplo, suporta codificação datetime em JSON imediatamente (com a versão mais recente).return {c.name: unicode(getattr(self, c.name)) for c in self.__table__.columns}
Você pode converter um RowProxy em um ditado como este:
Em seguida, serialize isso para JSON (você precisará especificar um codificador para coisas como
datetime
valores). Não é tão difícil se você deseja apenas um registro (e não uma hierarquia completa de registros relacionados).fonte
Eu recomendo usar marshmallow . Permite criar serializadores para representar suas instâncias de modelo com suporte a relações e objetos aninhados.
Aqui está um exemplo truncado de seus documentos. Veja o modelo ORM
Author
:Um esquema de marshmallow para essa classe é construído assim:
... e usado assim:
... produziria uma saída como esta:
Veja o exemplo completo do Flask-SQLAlchemy .
Uma biblioteca chamada
marshmallow-sqlalchemy
integra especificamente SQLAlchemy e marshmallow. Nessa biblioteca, o esquema para oAuthor
modelo descrito acima se parece com o seguinte:A integração permite que os tipos de campo sejam inferidos a partir dos
Column
tipos SQLAlchemy .marshmallow-sqlalchemy aqui.
fonte
Python 3.7+ e Flask 1.1+ podem usar o pacote de classes de dados embutido
A
/users/
rota agora retornará uma lista de usuários.Serializar automaticamente modelos relacionados
A resposta
jsonify(account)
seria essa.Substituir o codificador JSON padrão
fonte
data = request.json['user']; user = User(**data)
id: int = Column
funcionará, masid = Column
não funcionará, parece que VOCÊ DEVE declarar a digitação estática para o json serializar o campo, caso contrário, você obterá um{}
objeto vazio .pipenv install dataclasses
. E então vai funcionar muito bem.O pacote Flask-JsonTools possui uma implementação da classe JsonSerializableBase Base para seus modelos.
Uso:
Agora o
User
modelo é magicamente serializável.Se sua estrutura não é o Flask, você pode simplesmente pegar o código
fonte
import flask.ext.whatever
não é mais suportada no Flask 1.0.Por motivos de segurança, você nunca deve retornar todos os campos do modelo. Eu prefiro escolhê-los seletivamente.
A codificação json do Flask agora suporta UUID, data e hora (e foi adicionada
query
equery_class
para adb.Model
classe flask_sqlalchemy ). Atualizei o codificador da seguinte maneira:Com isso, opcionalmente, posso adicionar uma
__json__
propriedade que retorna a lista de campos que desejo codificar:Eu adiciono @jsonapi à minha visualização, retorno a lista de resultados e, em seguida, minha saída é a seguinte:
fonte
@jsonapi
a@app.route
em views.py etc), mas eu amo a simplicidade dele. Eu acho que é Flask barato acrescentou datetime, mas não data para que eu adicionei-me a json_encoder.py :value=...
^if isinstance(value, date):
^data[field] = datetime.combine(value, time.min).isoformat()
^else:
^try:...
Você pode usar a introspecção de SqlAlchemy da seguinte maneira:
Inspire-se com uma resposta aqui: Converter objeto de linha sqlalchemy em dict python
fonte
Uma explicação mais detalhada. No seu modelo, adicione:
O
str()
é para python 3, portanto, se você estiver usando python 2, useunicode()
. Deve ajudar a desserializar datas. Você pode removê-lo se não estiver lidando com eles.Agora você pode consultar o banco de dados como este
First()
é necessário para evitar erros estranhos.as_dict()
agora desserializará o resultado. Após a desserialização, ele está pronto para ser transformado em jsonfonte
Não é tão direto. Eu escrevi algum código para fazer isso. Ainda estou trabalhando nisso e ele usa a estrutura MochiKit. Ele basicamente traduz objetos compostos entre Python e Javascript usando um proxy e conversores JSON registrados.
O lado do navegador para objetos de banco de dados é o db.js Ele precisa da fonte básica de proxy Python no proxy.js .
No lado do Python, há o módulo proxy base . Finalmente, o codificador de objeto SqlAlchemy em webserver.py . Também depende dos extratores de metadados encontrados no arquivo models.py .
fonte
Enquanto a pergunta original remonta há algum tempo, o número de respostas aqui (e minhas próprias experiências) sugerem que é uma pergunta não trivial com muitas abordagens diferentes de complexidade variada com diferentes trade-offs.
É por isso que eu criei a biblioteca SQLAthanor que estende o ORM declarativo do SQLAlchemy com suporte configurável de serialização / desserialização que você pode querer dar uma olhada.
A biblioteca suporta:
dict
password
, mas nunca incluir um valor de saída )Você pode conferir os documentos abrangentes (espero!) Aqui: https://sqlathanor.readthedocs.io/en/latest
Espero que isto ajude!
fonte
Serialização e desserialização personalizadas.
"from_json" (método de classe) cria um objeto Model com base nos dados json.
"desserializar" poderia ser chamado apenas na instância e mesclar todos os dados do json na instância do Model.
"serialize" - serialização recursiva
A propriedade __write_only__ é necessária para definir propriedades somente de gravação ("password_hash", por exemplo).
fonte
Aqui está uma solução que permite selecionar as relações que você deseja incluir em sua saída, tão profundamente quanto você gostaria de ir. NOTA: Esta é uma reescrita completa, usando um dict / str como um argumento em vez de como uma lista. corrige algumas coisas ..
por exemplo, usando pessoa / família / lares / quartos ... transformando-o em json, tudo o que você precisa é
fonte
Eu pensei em jogar um pouco de golfe com este.
FYI: Estou usando automap_base pois temos um esquema projetado separadamente, de acordo com os requisitos comerciais. Acabei de começar a usar o SQLAlchemy hoje, mas a documentação afirma que automap_base é uma extensão do declarative_base que parece ser o paradigma típico no ORM do SQLAlchemy, então acredito que isso funcione.
Ele não gosta de seguir as chaves estrangeiras de acordo com a solução de Tjorriemorrie , mas simplesmente combina colunas com valores e manipula tipos de Python, str () - usando os valores das colunas. Nossos valores consistem em resultados de tipo de classe Python datetime.time e decimal.Decimal, para que ele faça o trabalho.
Espero que isso ajude qualquer transeunte!
fonte
Eu sei que este é um post bastante antigo. Tomei solução dada por @SashaB e modificado conforme minha necessidade.
Eu adicionei as seguintes coisas:
Meu código é o seguinte:
Espero que ajude alguém!
fonte
Use o serializador interno no SQLAlchemy:
Se você estiver transferindo o objeto entre as sessões, lembre-se de desanexar o objeto da sessão atual usando
session.expunge(obj)
. Para anexá-lo novamente, apenas façasession.add(obj)
.fonte
O código a seguir serializará o resultado sqlalchemy para json.
Chamando diversão,
fonte
O AlchemyEncoder é maravilhoso, mas às vezes falha com os valores decimais. Aqui está um codificador aprimorado que resolve o problema decimal -
fonte
Ao usar o sqlalchemy para conectar-se a um db I, esta é uma solução simples e altamente configurável. Use pandas.
fonte
Em Flask, isso funciona e manipula os campos de data e hora, transformando um campo do tipo
'time': datetime.datetime(2018, 3, 22, 15, 40)
em"time": "2018-03-22 15:40:00"
:fonte
O serializador embutido engasga com utf-8 não pode decodificar byte de início inválido para algumas entradas. Em vez disso, fui com:
fonte
Talvez você possa usar uma classe como esta
Com isso todos os objetos têm o
to_dict
métodofonte
Ao usar alguns sql bruto e objetos indefinidos, o uso de
cursor.description
apareceu para obter o que eu estava procurando:fonte
fonte
Minha opinião utilizando dicionários (muitos?):
Executando com flask (incluindo jsonify) e flask_sqlalchemy para imprimir saídas como JSON.
Chame a função com jsonify (serialize ()).
Funciona com todas as consultas SQLAlchemy que eu tentei até agora (executando o SQLite3)
fonte