Более простой способ создать объект JSON из SQLObject.

РЕДАКТИРОВАТЬ - взял код снизу и сделал так, чтобы он мог обрабатывать ForiegnKeys, десятичные числа (хотя я делаю очень принудительное преобразование с плавающей запятой). Теперь он возвращает dict, поэтому он может быть рекурсивным.

from sqlobject import SQLObject
from decimal import Decimal

def sqlobject_to_dict(obj):
    json_dict = {}
    cls_name = type(obj)
    for attr in vars(cls_name):
        if isinstance(getattr(cls_name, attr), property):
            attr_value = getattr(obj, attr)
            attr_class = type(attr_value)
            attr_parent = attr_class.__bases__[0]
            if isinstance(getattr(obj, attr), Decimal):
                json_dict[attr] = float(getattr(obj, attr))
            elif attr_parent == SQLObject:
                json_dict[attr] = sqlobject_to_dict(getattr(obj, attr))
            else:
                json_dict[attr] = getattr(obj, attr)

    return json_dict

РЕДАКТИРОВАТЬ - изменено, чтобы добавить фактическую модель данных - есть сгенерированные значения, к которым необходимо получить доступ, и столбцы Decimal(), с которыми также необходимо работать.

Итак, я видел это: вернуть таблицу SQL как JSON в python но на самом деле это не то, что я ищу - это "грубая сила" - вам нужно знать имена атрибутов объекта, чтобы сгенерировать ответ JSON.

Я хотел бы сделать что-то вроде этого (имя класса и его атрибуты не важны)

class BJCPStyle(SQLObject):
    name = UnicodeCol(length=128, default=None)
    beer_type = UnicodeCol(length=5, default=None)
    category = ForeignKey('BJCPCategory')
    subcategory = UnicodeCol(length=1, default=None)
    aroma = UnicodeCol(default=None)
    appearance = UnicodeCol(default=None)
    flavor = UnicodeCol(default=None)
    mouthfeel = UnicodeCol(default=None)
    impression = UnicodeCol(default=None)
    comments = UnicodeCol(default=None)
    examples = UnicodeCol(default=None)
    og_low = SGCol(default=None)
    og_high = SGCol(default=None)
    fg_low = SGCol(default=None)
    fg_high = SGCol(default=None)
    ibu_low = IBUCol(default=None)
    ibu_high = IBUCol(default=None)
    srm_low = SRMCol(default=None)
    srm_high = SRMCol(default=None)
    abv_low = DecimalCol(size=3, precision=1, default=None)
    abv_high = DecimalCol(size=3, precision=1, default=None)
    versions = Versioning()

    def _get_combined_category_id(self):
        return "%s%s" % (self.category.category_id, self.subcategory)

    def _get_og_range(self):
        low = self._SO_get_og_low()
        high = self._SO_get_og_high()

        if low == 0 and high == 0:
            return "varies"
        else:
            return "%.3f - %.3f" % (low, high)

    def _get_fg_range(self):
        low = self._SO_get_fg_low()
        high = self._SO_get_fg_high()

        if low == 0 and high == 0:
            return "varies"
        else:
            return "%.3f - %.3f" % (low, high)

    def _get_srm_range(self):
        low = self._SO_get_srm_low()
        high = self._SO_get_srm_high()

        if low == 0 and high == 0:
            return "varies"
        else:
            return "%.1f - %.1f" % (low, high)

    def _get_abv_range(self):
        low = self._SO_get_abv_low()
        high = self._SO_get_abv_high()

        if low == 0 and high == 0:
            return "varies"
        else:
            return "%.2f%% - %.2f%%" % (low, high)

    def _get_ibu_range(self):
        low = self._SO_get_ibu_low()
        high = self._SO_get_ibu_high()

        if low == 0 and high == 0:
            return "varies"
        else:
            return "%i - %i" % (low, high)    

Есть ли простой способ, питонический способ написать эту волшебную функцию to_json()?


person tkone    schedule 07.12.2011    source источник


Ответы (3)


Вы можете использовать модуль python json с SQLObject sqlmeta. Как это:

def to_json(obj):
    return json.dumps(dict((c, getattr(obj, c)) for c in obj.sqlmeta.columns))

Когда я запускаю это с вашим классом Foo, я получаю:

>>> print to_json(f)
{"bar": "test", "lulz": "only for the", "baz": true}

Изменить: если вы хотите включить магические атрибуты в вашей строке json, и вы не против использовать что-то вроде взлома, вы можете злоупотреблять тем фактом, что атрибуты вашего объекта являются свойствами python. Например, если я добавлю магический атрибут foo в исходный пример класса:

class Foo(SQLObject):
    bar = UnicodeCol(length=128)
    baz = BoolCol(default=True)
    lulz = UnicodeCol(length=256)

    def _get_foo(self):
        return "foo"

Затем я могу определить функцию to_json() следующим образом:

def to_json(obj):
    cls = type(obj)
    d = dict((c, getattr(obj, c)) for c in vars(cls) if isinstance(getattr(cls, c), property))
    return json.dumps(d)

Теперь, если я сделаю это:

f = Foo(bar = "test", lulz = "only for the")
print to_json(f)

Я получаю следующий результат:

{"baz": true, "lulz": "only for the", "bar": "test", "foo": "foo"}
person srgerg    schedule 07.12.2011
comment
Это работает, но я должен был опубликовать всю свою модель данных — с ней происходит гораздо больше, чем поможет sqlmeta.columns. Обратите внимание на методы get*_range(). Десятичные столбцы на самом деле не нужны в результатах JSON, поэтому их легко отфильтровать с помощью оператора if. - person tkone; 08.12.2011
comment
Я отредактировал свой ответ с помощью хака, который будет включать в себя магические атрибуты. - person srgerg; 09.12.2011
comment
принято и проголосовано! дерьмо, я никогда не собирал тип вместе - это то, как я отфильтровывал десятичные поля (которые фактически генерируют эти производные данные). Я бы дал вам больше репутации, если бы мог! - person tkone; 09.12.2011

import json

json.dumps(obj_instance.sqlmeta.asDict())

В моем случае этот объект содержал дату и время, которые json не сериализует, поэтому я сделал что-то вроде этого:

json.dumps(dict((k, str(v)) for (k,v) in obj_instance.sqlmeta.asDict().items()))
person csoria    schedule 11.08.2014

Что-то вроде этого ...

class MyTable( sqlobject.SQLObject ):
    # ... your columns ... 

json.dumps({
    'MyTable': [row.sqlmeta.asDict() for row in MyTable.select()]
}, indent=4, sort_keys=True ) 

Предположим, у вас есть список производных классов sqlobject.SQLObject под названием «Таблицы».

Tables = [MyTable, ...]

def dump():
    r={}
    for t in Tables:
        r[t.__name__] = [row.sqlmeta.asDict() for row in t.select()]
    return json.dumps(r, indent=4, sort_keys=True)
person user373839    schedule 11.03.2017