从SQLObject创建JSON对象的更简单方法

时间:2011-12-07 22:04:54

标签: json python sqlobject

编辑 - 从下面获取代码并使其能够处理ForiegnKeys,十进制数字(尽管我正在进行非常强制的浮动转换)。它现在返回一个字典,因此可以递归。

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()列。

所以我看到了这个:return SQL table as JSON in 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)    

是否有一种简单的方法,pythonic方式来编写那个神奇的to_json()函数?

3 个答案:

答案 0 :(得分:3)

您可以将python json module与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字符串中包含magic attributes并且你不介意使用某种黑客攻击,你可能会滥用你的对象属性的事实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"}

答案 1 :(得分:0)

import json

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

在我的情况下,这个对象包含json没有序列化的日期时间,所以我做了这样的事情:

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

答案 2 :(得分:0)

像这样......

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)