Django ma dobrą automatyczną serializację modeli ORM zwróconych z DB do formatu JSON.
Jak serializować wynik zapytania SQLAlchemy do formatu JSON?
Próbowałem, jsonpickle.encode
ale koduje sam obiekt zapytania. Próbowałem, json.dumps(items)
ale powraca
TypeError: <Product('3', 'some name', 'some desc')> is not JSON serializable
Czy naprawdę tak trudno jest serializować obiekty ORM SQLAlchemy do JSON / XML? Czy nie ma dla niego domyślnego serializatora? Obecnie bardzo powszechne jest serializowanie wyników zapytań ORM.
Potrzebuję tylko zwrócić JSON lub XML reprezentację wyników zapytania SQLAlchemy.
Wynik zapytania o obiekty SQLAlchemy w formacie JSON / XML jest potrzebny do użycia w javascript datagird (JQGrid http://www.trirand.com/blog/ )
python
json
sqlalchemy
Zelid
źródło
źródło
Odpowiedzi:
Płaska realizacja
Możesz użyć czegoś takiego:
a następnie przekonwertować na JSON, używając:
Zignoruje pola, które nie są kodowalne (ustaw je na „Brak”).
Nie rozszerza relacji automatycznie (ponieważ może to prowadzić do odwołań do siebie i zapętlać na zawsze).
Rekurencyjna, nieokrągła implementacja
Jeśli jednak wolisz zapętlać się w nieskończoność, możesz użyć:
A następnie koduj obiekty za pomocą:
Spowoduje to zakodowanie wszystkich dzieci i wszystkich ich dzieci oraz wszystkich ich dzieci ... Potencjalnie, w zasadzie, możesz zakodować całą bazę danych. Kiedy osiągnie coś, co wcześniej było zakodowane, zakoduje to jako „Brak”.
Rekurencyjna, być może cykliczna, selektywna implementacja
Inną alternatywą, prawdopodobnie lepszą, jest możliwość określenia pól, które chcesz rozwinąć:
Możesz teraz zadzwonić za pomocą:
Aby rozszerzyć tylko pola SQLAlchemy, na przykład „rodzice”.
źródło
online_order
iaddress
zarówno związek zuser
, jakonline_order
i związek zaddress
. Gdybym chciał serializować to wszystko, musiałbym dołączyćaddress
dofields_to_expand
, ale nie chciałbym nadmiarowo serializowaćaddress
ze względu na jego związek z jednymuser
i drugimonline_order
.for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
tak, aby czytałfor field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata' and not x.startswith('query')]:
. Należy pamiętać, że to rozwiązanie zapobiegnie posiadaniu własności / relacji z nazwą „zapytanie”Możesz po prostu wyprowadzić obiekt jako słownik:
A potem używasz
User.as_dict()
do serializacji swojego obiektu.Jak wyjaśniono w Konwertowanie obiektu wiersza sqlalchemy na Python Dict
źródło
JSONEncoder
przedmiot. Można go podklasować, aby zdefiniować własny koder dla niektórych obiektów, w tym datetime. Zwróć uwagę, żeFlask
na przykład obsługuje kodowanie datetime w JSON po wyjęciu z pudełka (z najnowszą wersją).return {c.name: unicode(getattr(self, c.name)) for c in self.__table__.columns}
Możesz przekonwertować RowProxy na taki słownik:
Następnie serializuj to do JSON (będziesz musiał określić koder dla takich rzeczy jak
datetime
wartości). Nie jest to takie trudne, jeśli potrzebujesz tylko jednego rekordu (a nie pełnej hierarchii powiązanych rekordów).źródło
Polecam używanie pianki . Pozwala tworzyć serializatory reprezentujące instancje modelu z obsługą relacji i zagnieżdżonych obiektów.
Oto skrócony przykład z ich dokumentów. Weź model ORM
Author
:Schemat ptasie mleczko dla tej klasy jest zbudowany w następujący sposób:
... i używane w ten sposób:
... wygeneruje taki wynik:
Zobacz ich pełny przykład Flask-SQLAlchemy .
Biblioteka o nazwie
marshmallow-sqlalchemy
specjalnie integruje SQLAlchemy i piankę. W tej bibliotece schematAuthor
opisanego powyżej modelu wygląda następująco:Dzięki integracji typy pól można wywnioskować na podstawie
Column
typów SQLAlchemy .marshmallow-sqlalchemy tutaj.
źródło
Python 3.7+ i Flask 1.1+ mogą korzystać z wbudowanego pakietu klas danych
/users/
Trasa będzie teraz powrócić do listy użytkowników.Automatyczne serializowanie powiązanych modeli
Odpowiedź
jsonify(account)
byłaby taka.Zastąp domyślny koder JSON
źródło
data = request.json['user']; user = User(**data)
id: int = Column
zadziała, aleid = Column
nie, wydaje się, że MUSISZ zadeklarować wpisywanie statyczne, aby json zserializował pole, w przeciwnym razie otrzymasz pusty{}
obiekt.pipenv install dataclasses
. A potem wszystko będzie dobrze.Pakiet Flask-JsonTools ma implementację JsonSerializableBase klasy podstawowej dla twoich modeli.
Stosowanie:
Teraz
User
model jest magicznie serializowalny.Jeśli twój framework nie jest Flask, możesz po prostu pobrać kod
źródło
import flask.ext.whatever
nie jest już obsługiwana w Flask 1.0.Ze względów bezpieczeństwa nigdy nie należy zwracać wszystkich pól modelu. Wolę je selektywnie wybierać.
Kodowanie json Flask obsługuje teraz UUID, datę
query
iquery_class
godzinę oraz relacje (i dodano oraz dladb.Model
klasy flask_sqlalchemy ). Zaktualizowałem koder w następujący sposób:Dzięki temu mogę opcjonalnie dodać
__json__
właściwość, która zwraca listę pól, które chcę zakodować:Dodaję @jsonapi do mojego widoku, zwracam listę wyników, a następnie moje wyniki są następujące:
źródło
@jsonapi
do@app.route
w views.py itp.), Ale uwielbiam jego prostotę. Myślę, że to tanie Data dodania kolby, ale nie data, więc dodałem ją sam do json_encoder.py :value=...
^if isinstance(value, date):
^data[field] = datetime.combine(value, time.min).isoformat()
^else:
^try:...
Możesz użyć introspekcji SqlAlchemy w następujący sposób:
Zainspiruj się tutaj: Konwertuj obiekt wiersza sqlalchemy na Python Dict
źródło
Bardziej szczegółowe wyjaśnienie. W swoim modelu dodaj:
str()
Jest pytona 3 tak, jeśli Pythonie 2 użyciaunicode()
. Powinno to pomóc w deserializacji dat. Możesz go usunąć, jeśli nie masz z nimi do czynienia.Możesz teraz przeszukiwać bazę danych w ten sposób
First()
jest potrzebny, aby uniknąć dziwnych błędów.as_dict()
teraz deserializuje wynik. Po deserializacji jest gotowy do zmiany w Jsonźródło
To nie jest takie proste. Napisałem kod, aby to zrobić. Nadal nad tym pracuję, i korzysta z frameworka MochiKit. Zasadniczo tłumaczy obiekty złożone między Pythonem i Javascript przy użyciu proxy i zarejestrowanych konwerterów JSON.
Stroną przeglądarki dla obiektów bazy danych jest db.js. Potrzebuje podstawowego źródła proxy Python w proxy.js .
Po stronie Pythona znajduje się podstawowy moduł proxy . Następnie koder obiektów SqlAlchemy w webserver.py . Zależy to również od ekstraktorów metadanych znajdujących się w pliku models.py .
źródło
Choć pierwotne pytanie się cofało, liczba odpowiedzi tutaj (i moich własnych doświadczeń) sugeruje, że jest to pytanie nietrywialne z wieloma różnymi podejściami o różnym stopniu złożoności z różnymi kompromisami.
Właśnie dlatego zbudowałem bibliotekę SQLAthanor, która rozszerza deklaratywną ORM SQLAlchemy o konfigurowalną obsługę serializacji / deserializacji , na którą warto spojrzeć.
Biblioteka obsługuje:
dict
password
, ale nigdy nie dołączaj wartości wychodzącej )Możesz sprawdzić (mam nadzieję!) Obszerne dokumenty tutaj: https://sqlathanor.readthedocs.io/en/latest
Mam nadzieję że to pomoże!
źródło
Niestandardowa serializacja i deserializacja.
„from_json” (metoda klasy) buduje obiekt Model na podstawie danych json.
„deserializować” można wywołać tylko w instancji i scalić wszystkie dane z json w instancję Model.
„serialize” - serializacja rekurencyjna
Właściwość __write_only__ jest potrzebna do zdefiniowania właściwości tylko do zapisu (na przykład „ skrót_hasła ”).
źródło
Oto rozwiązanie, które pozwala wybrać relacje, które chcesz uwzględnić w swoich wynikach tak głęboko, jak chcesz. UWAGA: Jest to całkowite ponowne zapisanie, biorąc dict / str jako argument zamiast listy. naprawia niektóre rzeczy ..
więc na przykład używając osoby / rodziny / domu / pokoju ... zamieniając go w json, wszystko czego potrzebujesz to
źródło
Myślałem, że zagram w ten golf z małym kodem.
FYI: Korzystam z automap_base, ponieważ mamy osobno zaprojektowany schemat zgodnie z wymaganiami biznesowymi. Właśnie zacząłem używać SQLAlchemy dzisiaj, ale dokumentacja stwierdza, że automap_base jest rozszerzeniem do deklaratywnej_bazy, która wydaje się być typowym paradygmatem w SQLAlchemy ORM, więc uważam, że to powinno działać.
Nie nabiera ochoty śledzić kluczy obcych w rozwiązaniu Tjorriemorrie , ale po prostu dopasowuje kolumny do wartości i obsługuje typy Pythona poprzez str () - wartości kolumn. Nasze wartości składają się z wyników typu klasy Python datetime.time i decimal.Decimal, aby wykonać zadanie.
Mam nadzieję, że pomoże to przechodniom!
źródło
Wiem, że to dość starszy post. Wziąłem rozwiązanie podane przez @SashaB i zmodyfikowałem zgodnie z moimi potrzebami.
Dodałem do niego następujące rzeczy:
Mój kod jest następujący:
Mam nadzieję, że to komuś pomaga!
źródło
Użyj wbudowanego serializatora w SQLAlchemy:
Jeśli przenosisz obiekt między sesjami, pamiętaj, aby odłączyć obiekt od bieżącej sesji za pomocą
session.expunge(obj)
. Aby dołączyć go ponownie, po prostu zróbsession.add(obj)
.źródło
poniższy kod serializuje wynik sqlalchemy do json.
Wzywając zabawy
źródło
AlchemyEncoder jest wspaniały, ale czasami zawodzi przy wartościach dziesiętnych. Oto ulepszony koder, który rozwiązuje problem dziesiętny -
źródło
Gdy używasz sqlalchemy do łączenia się z db I, jest to proste rozwiązanie, które można w bardzo dużym stopniu konfigurować. Używaj pand.
źródło
źródło
Pod Flaskem działa i obsługuje pola czasu danych, przekształcając pole typu
'time': datetime.datetime(2018, 3, 22, 15, 40)
w"time": "2018-03-22 15:40:00"
:źródło
Wbudowane dławiki serializatora z utf-8 nie mogą dekodować nieprawidłowego bajtu początkowego dla niektórych danych wejściowych. Zamiast tego poszedłem z:
źródło
Może możesz użyć takiej klasy
Dzięki temu wszystkie obiekty mają
to_dict
metodęźródło
Podczas korzystania z niektórych surowych obiektów sql i niezdefiniowanych,
cursor.description
pojawiało się używanie, aby uzyskać to, czego szukałem:źródło
Moje podejście z wykorzystaniem (zbyt wielu?) Słowników:
Uruchamianie z flask (w tym jsonify) i flask_sqlalchemy, aby wydrukować wyniki jako JSON.
Wywołaj funkcję za pomocą jsonify (serialize ()).
Działa ze wszystkimi zapytaniami SQLAlchemy, które próbowałem do tej pory (działając SQLite3)
źródło