【问题标题】:Easier way to create a JSON object from an SQLObject从 SQLObject 创建 JSON 对象的更简单方法
【发布时间】:2011-12-07 22:04:53
【问题描述】:

编辑——从下面获取代码并使其可以处理 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)    

有没有一种简单的 Python 方式来编写这个神奇的 to_json() 函数?

【问题讨论】:

    标签: json python sqlobject


    【解决方案1】:

    您可以将 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"}
    

    【讨论】:

    • 这行得通,但我应该发布我的整个数据模型——它的作用远不止 sqlmeta.columns 所能提供的帮助。注意 get*_range() 方法。 JSON 结果中实际上不需要小数列,因此使用 if 语句很容易过滤掉这些列
    • 我已经用包含魔法属性的 hack 编辑了我的答案。
    • 接受并点赞!废话我从来没有把类型的东西放在一起——这就是我过滤小数字段(实际上生成派生数据)的方式。如果可以的话,我会给你更多的代表!
    【解决方案2】:
    import json
    
    json.dumps(obj_instance.sqlmeta.asDict())
    

    在我的例子中,这个对象包含 json 不序列化的日期时间,所以我做了这样的事情:

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

    【讨论】:

      【解决方案3】:

      类似这样的...

      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)
      

      【讨论】:

        猜你喜欢
        • 2016-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-03
        • 1970-01-01
        • 1970-01-01
        • 2011-11-27
        • 1970-01-01
        相关资源
        最近更新 更多