EDIT - a pris le code d'en bas et l'a fait pour qu'il puisse gérer les ForiegnKeys, les nombres décimaux (bien que je fasse une conversion flottante très forcée). Il renvoie maintenant un dict afin qu'il puisse être récursif.

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

EDIT - modifié pour ajouter le modèle de données réel - il existe des valeurs générées auxquelles il faut accéder et des colonnes Decimal () qui doivent également être traitées.

J'ai donc vu ceci: retourner la table SQL en JSON en python mais ce n'est pas vraiment ce que je recherche - c'est de la "force brute" - vous devez connaître les noms des attributs de l'objet afin de générer la réponse JSON.

Ce que j'aimerais faire, c'est quelque chose comme ça (le nom de la classe et ses attributs ne sont pas importants)

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)    

Existe-t-il un moyen simple et pythonique d'écrire cette fonction magique de to_json ()?

1
tkone 8 déc. 2011 à 02:04

3 réponses

Meilleure réponse

Vous pouvez utiliser le module json python avec le SQLObject sqlmeta classe. Comme ça:

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

Lorsque je lance ceci avec votre classe Foo, j'obtiens:

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

Modifier: si vous souhaitez inclure des attributs magiques dans votre chaîne json et cela ne vous dérange pas d'utiliser quelque chose d'un hack, vous pourriez abuser du fait que les attributs de votre objet sont des propriétés python. Par exemple, si j'ajoute un attribut magique foo à votre exemple de classe d'origine:

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

    def _get_foo(self):
        return "foo"

Ensuite, je peux définir la fonction to_json() comme ceci:

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)

Maintenant, si je fais ça:

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

J'obtiens le résultat suivant:

{"baz": true, "lulz": "only for the", "bar": "test", "foo": "foo"}
3
srgerg 9 déc. 2011 à 00:21
import json

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

Dans mon cas, cet objet contenait des heures que json ne sérialise pas, j'ai donc fait quelque chose comme ceci:

json.dumps(dict((k, str(v)) for (k,v) in obj_instance.sqlmeta.asDict().items()))
0
csoria 11 août 2014 à 20:39

Quelque chose comme ça ...

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

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

Supposons que vous ayez une liste de classes dérivées sqlobject.SQLObject appelées «Tables»

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)
0
user373839 11 mars 2017 à 02:22