2016-04-05 10 views
6

के लिए कस्टम JSON एन्कोडर का उपयोग करके मैं कुछ PostgreSQL डेटाबेस तक पहुंचने के लिए SQLAlchemy की मुख्य लाइब्रेरी का उपयोग कर रहा हूं।SQLAlchemy के PostgreSQL JSONB कार्यान्वयन

create table foo (j jsonb); 

और निम्नलिखित अजगर कोड:

from decimal import * 
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey, DateTime 
from sqlalchemy.dialects.postgresql import JSONB 
metadata = MetaData(schema="public") 
foo = Table('foo', metadata,Column('f', JSONB)) 
d = Decimal(2) 
ins = foo.insert().values(j = {'d': d}) 
# assuming engine is a valid sqlalchemy's connection 
engine.execute(ins) 

यह अंतिम वाक्य निम्नलिखित त्रुटि के साथ विफल:

StatementError("(builtins.TypeError) Decimal('2') is not JSON serializable",) 

यही वजह है कि मैं इस पूछ रहा हूँ मैं निम्न तालिका है पर विचार करें प्रश्न: क्या पोस्टग्रेएसक्यूएल बोली में जेसन डेटा एन्कोड करते समय एसक्यूएलकेमी के लिए एक कस्टम एन्कोडर निर्दिष्ट करने का कोई तरीका है?

उत्तर

11

यह create_engine को json_serializer कीवर्ड तर्क के माध्यम से समर्थित है के रूप में sqlalchemy.dialects.postgresql.JSON के तहत दस्तावेज:

def _default(val): 
    if isinstance(val, Decimal): 
     return str(val) 
    raise TypeError() 

def dumps(d): 
    return json.dumps(d, default=_default) 

engine = create_engine(..., json_serializer=dumps) 
+0

बहुत बढ़िया। प्रलेखन के उस हिस्से को याद किया। कल इसे आजमाएं और तदनुसार जवाब स्वीकार करें। धन्यवाद!! –

3

अगर आप मेरी तरह, एक अच्छा तरीका यह कुप्पी के SQLAlchemy के साथ चलाने के लिए मिल रहे हैं, तो यह क्या है मैंने किया। यदि आप मानक लाइब्रेरी json मॉड्यूल के बजाय flask.json आयात और पास करते हैं, तो आपको तिथियों, डेटाटाइम्स और uuid.UUID उदाहरणों का स्वचालित deserialization मिल जाएगा।

class HackSQLAlchemy(SQLAlchemy): 
    """ Ugly way to get SQLAlchemy engine to pass the Flask JSON serializer 
    to `create_engine`. 

    See https://github.com/mitsuhiko/flask-sqlalchemy/pull/67/files 

    """ 

    def apply_driver_hacks(self, app, info, options): 
     options.update(json_serializer=json.dumps) 
     super(HackSQLAlchemy, self).apply_driver_hacks(app, info, options) 
1

आप बोतल का उपयोग कर रहे हैं, तो आप पहले से ही एक विस्तारित JSONEncoder flask.json जो UUID संभालती में परिभाषित किया गया है, लेकिन नहीं Decimal है। यह @ univerio के जवाब के रूप में json_serializer परम साथ SQLAlchemy इंजन में मैप किया जा सकता है:

from flask import json 

engine = create_engine(
    app.config['SQLALCHEMY_DATABASE_URI'], 
    convert_unicode=True, 
    json_serializer=json.dumps, 
) 

आप आगे निम्नलिखित के साथ decimal.Decimal समर्थन करने के लिए बोतल JSONEncoder विस्तार कर सकते हैं:

import decimal 

from flask import json 

class CustomJSONEncoder(json.JSONEncoder): 
    """ 
    Override Flask's JSONEncoder with the single method `default`, which 
    is called when the encoder doesn't know how to encode a specific type. 
    """ 
    def default(self, obj): 
     if type(obj) is decimal.Decimal: 
      return str(obj) 
     else: 
      # raises TypeError: obj not JSON serializable 
      return json.JSONEncoder.default(self, obj) 

def init_json(app): 
    """ 
    Use custom JSON encoder with Flask 
    """ 
    app.json_encoder = CustomJSONEncoder 
संबंधित मुद्दे