Tôi đang lưu trữ JSON dưới dạng blob/text trong một cột bằng cách sử dụng MySQL. Có một cách đơn giản để chuyển đổi này thành một dict bằng cách sử dụng python/SQLAlchemy?SQLAlchemy JSON dưới dạng blob/text
Trả lời
Bạn có thể rất dễ dàng create your own type với SQLAlchemy
Đối với phiên bản SQLAlchemy> = 0.7, hãy kiểm tra Yogesh's answer dưới
import jsonpickle
import sqlalchemy.types as types
class JsonType(types.MutableType, types.TypeDecorator):
impl = types.Unicode
def process_bind_param(self, value, engine):
return unicode(jsonpickle.encode(value))
def process_result_value(self, value, engine):
if value:
return jsonpickle.decode(value)
else:
# default can also be a list
return {}
này có thể được sử dụng khi bạn đang xác định bảng của bạn (ví dụ sử dụng elixir):
from elixir import *
class MyTable(Entity):
using_options(tablename='my_table')
foo = Field(String, primary_key=True)
content = Field(JsonType())
active = Field(Boolean, default=True)
Bạn cũng có thể sử dụng trình tuần tự json khác với jsonpickle.
Làm thế nào về json.loads()?
>>> d= {"foo":1, "bar":[2,3]}
>>> s='{"foo":1, "bar":[2,3]}'
>>> import json
>>> json.loads(s) == d
True
cảm ơn, có cách nào để tự động làm điều đó không? giống như kích hoạt trong sqlalchemy. – Timmy
Tôi nghĩ rằng ví dụ JSON từ các tài liệu SQLAlchemy cũng đáng nhắc đến:
http://www.sqlalchemy.org/docs/core/types.html#marshal-json-strings
Tuy nhiên, tôi nghĩ rằng nó có thể được cải thiện để được ít nghiêm ngặt về NULL và chuỗi rỗng:
class JSONEncodedDict(TypeDecorator):
impl = VARCHAR
def process_bind_param(self, value, dialect):
if value is None:
return None
return json.dumps(value, use_decimal=True)
def process_result_value(self, value, dialect):
if not value:
return None
return json.loads(value, use_decimal=True)
Câu trả lời này làm việc cho tôi mà không cần chạm vào types.py. –
NB: Điều này sẽ chỉ hoạt động nếu bạn coi giá trị là không thay đổi. Vì vậy, bạn gán thuộc tính đối tượng một 'dict' đầy đủ. Nếu bạn cố gắng sửa đổi chỉ các phần tử của 'dict', sqlalchemy sẽ không đăng ký các thay đổi và chúng sẽ không được lưu lại. Xem 'sqlalchemy.ext.mutable.Mutable' về cách thay đổi điều đó. –
Đây là những gì tôi nghĩ ra dựa trên hai câu trả lời ở trên.
import json
class JsonType(types.TypeDecorator):
impl = types.Unicode
def process_bind_param(self, value, dialect):
if value :
return unicode(json.dumps(value))
else:
return {}
def process_result_value(self, value, dialect):
if value:
return json.loads(value)
else:
return {}
Đã xảy ra sự cố với quá trình lưu đã được giải quyết bằng cách sử dụng từ điển có thể thay đổi. http://docs.sqlalchemy.org/en/rel_0_8/orm/extensions/mutable.html –
sqlalchemy.types.MutableType
đã bị phản đối (v0.7 trở đi), các documentation recommends sử dụng sqlalchemy.ext.mutable
để thay thế.
Tôi đã tìm thấy Git gist bởi dbarnett mà tôi đã thử nghiệm để sử dụng. Nó đã làm việc tốt cho đến nay, cho cả từ điển và danh sách.
dán dưới đây cho hậu thế:
import simplejson
import sqlalchemy
from sqlalchemy import String
from sqlalchemy.ext.mutable import Mutable
class JSONEncodedObj(sqlalchemy.types.TypeDecorator):
"""Represents an immutable structure as a json-encoded string."""
impl = String
def process_bind_param(self, value, dialect):
if value is not None:
value = simplejson.dumps(value)
return value
def process_result_value(self, value, dialect):
if value is not None:
value = simplejson.loads(value)
return value
class MutationObj(Mutable):
@classmethod
def coerce(cls, key, value):
if isinstance(value, dict) and not isinstance(value, MutationDict):
return MutationDict.coerce(key, value)
if isinstance(value, list) and not isinstance(value, MutationList):
return MutationList.coerce(key, value)
return value
@classmethod
def _listen_on_attribute(cls, attribute, coerce, parent_cls):
key = attribute.key
if parent_cls is not attribute.class_:
return
# rely on "propagate" here
parent_cls = attribute.class_
def load(state, *args):
val = state.dict.get(key, None)
if coerce:
val = cls.coerce(key, val)
state.dict[key] = val
if isinstance(val, cls):
val._parents[state.obj()] = key
def set(target, value, oldvalue, initiator):
if not isinstance(value, cls):
value = cls.coerce(key, value)
if isinstance(value, cls):
value._parents[target.obj()] = key
if isinstance(oldvalue, cls):
oldvalue._parents.pop(target.obj(), None)
return value
def pickle(state, state_dict):
val = state.dict.get(key, None)
if isinstance(val, cls):
if 'ext.mutable.values' not in state_dict:
state_dict['ext.mutable.values'] = []
state_dict['ext.mutable.values'].append(val)
def unpickle(state, state_dict):
if 'ext.mutable.values' in state_dict:
for val in state_dict['ext.mutable.values']:
val._parents[state.obj()] = key
sqlalchemy.event.listen(parent_cls, 'load', load, raw=True, propagate=True)
sqlalchemy.event.listen(parent_cls, 'refresh', load, raw=True, propagate=True)
sqlalchemy.event.listen(attribute, 'set', set, raw=True, retval=True, propagate=True)
sqlalchemy.event.listen(parent_cls, 'pickle', pickle, raw=True, propagate=True)
sqlalchemy.event.listen(parent_cls, 'unpickle', unpickle, raw=True, propagate=True)
class MutationDict(MutationObj, dict):
@classmethod
def coerce(cls, key, value):
"""Convert plain dictionary to MutationDict"""
self = MutationDict((k,MutationObj.coerce(key,v)) for (k,v) in value.items())
self._key = key
return self
def __setitem__(self, key, value):
dict.__setitem__(self, key, MutationObj.coerce(self._key, value))
self.changed()
def __delitem__(self, key):
dict.__delitem__(self, key)
self.changed()
class MutationList(MutationObj, list):
@classmethod
def coerce(cls, key, value):
"""Convert plain list to MutationList"""
self = MutationList((MutationObj.coerce(key, v) for v in value))
self._key = key
return self
def __setitem__(self, idx, value):
list.__setitem__(self, idx, MutationObj.coerce(self._key, value))
self.changed()
def __setslice__(self, start, stop, values):
list.__setslice__(self, start, stop, (MutationObj.coerce(self._key, v) for v in values))
self.changed()
def __delitem__(self, idx):
list.__delitem__(self, idx)
self.changed()
def __delslice__(self, start, stop):
list.__delslice__(self, start, stop)
self.changed()
def append(self, value):
list.append(self, MutationObj.coerce(self._key, value))
self.changed()
def insert(self, idx, value):
list.insert(self, idx, MutationObj.coerce(self._key, value))
self.changed()
def extend(self, values):
list.extend(self, (MutationObj.coerce(self._key, v) for v in values))
self.changed()
def pop(self, *args, **kw):
value = list.pop(self, *args, **kw)
self.changed()
return value
def remove(self, value):
list.remove(self, value)
self.changed()
def JSONAlchemy(sqltype):
"""A type to encode/decode JSON on the fly
sqltype is the string type for the underlying DB column.
You can use it like:
Column(JSONAlchemy(Text(600)))
"""
class _JSONEncodedObj(JSONEncodedObj):
impl = sqltype
return MutationObj.as_mutable(_JSONEncodedObj)
Dựa trên câu trả lời @snapshoe và để trả lời @ bình luận Timmy:
Bạn có thể làm điều đó bằng cách sử dụng tài sản. Dưới đây là một ví dụ về một bảng:
class Providers(Base):
__tablename__ = "providers"
id = Column(
Integer,
Sequence('providers_id', optional=True),
primary_key=True
)
name = Column(Unicode(40), index=True)
_config = Column("config", Unicode(2048))
@property
def config(self):
if not self._config:
return {}
return json.loads(self._config)
@config.setter
def config(self, value):
self._config = json.dumps(value)
def set_config(self, field, value):
config = self.config
config[field] = value
self.config = config
def get_config(self):
if not self._config:
return {}
return json.loads(self._config)
def unset_config(self, field):
config = self.get_config()
if field in config:
del config[field]
self.config = config
Bây giờ bạn có thể sử dụng nó trên một đối tượng Providers()
:
>>> p = Providers()
>>> p.set_config("foo", "bar")
>>> p.get_config()
{"foo": "bar"}
>>> a.config
{u'foo': u'bar'}
Tôi biết đây là một câu hỏi cũ thậm chí có thể chết, nhưng tôi hy vọng điều này có thể giúp đỡ người khác .
Có một công thức cho việc này trong official documentation:
from sqlalchemy.types import TypeDecorator, VARCHAR
import json
class JSONEncodedDict(TypeDecorator):
"""Represents an immutable structure as a json-encoded string.
Usage::
JSONEncodedDict(255)
"""
impl = VARCHAR
def process_bind_param(self, value, dialect):
if value is not None:
value = json.dumps(value)
return value
def process_result_value(self, value, dialect):
if value is not None:
value = json.loads(value)
return value
Như một cập nhật cho các câu trả lời trước đó, mà chúng tôi đã sử dụng thành công cho đến nay. Kể từ MySQL 5.7 và SQLAlchemy 1.1, bạn có thể sử dụng native MySQL JSON data type, cung cấp cho bạn hiệu suất tốt hơn và toàn bộ miễn phí range of operators.
Nó cũng cho phép bạn tạo virtual secondary indexes trên các phần tử JSON.
Nhưng tất nhiên bạn sẽ tự khóa mình khi chạy ứng dụng của bạn trên MySQL chỉ khi di chuyển logic vào cơ sở dữ liệu.
- 1. phím json dưới dạng số
- 2. window.location.search truy vấn dưới dạng JSON
- 3. HTTPResponse dưới dạng JSON trong Java
- 4. Định dạng SQLAlchemy mã
- 5. Cách nhận phản hồi dưới dạng định dạng json (ứng dụng/json) trong yii?
- 6. trả về bảng SQL dưới dạng JSON trong python
- 7. MVC trả về một phần xem dưới dạng JSON
- 8. Gửi phản hồi Json dưới dạng Chuỗi và Số nguyên ...
- 9. Cách trả về giá trị từ Python dưới dạng JSON?
- 10. Jquery - Lưu trữ phản hồi Ajax jSON dưới dạng biến
- 11. Đăng mảng dưới dạng JSON tới Bộ điều khiển MVC
- 12. SQL 2008: trả về hàng dữ liệu dưới dạng JSON?
- 13. cách gửi biểu mẫu dưới dạng đối tượng JSON
- 14. JSON khác với dữ liệu JSON lớn, tìm một số JSON dưới dạng tập hợp con của một JSON khác
- 15. $ .post() không gửi dữ liệu dưới dạng json nhưng dưới dạng x-www-form-urlencoded thay vì
- 16. Google Chrome hiển thị phản hồi JSON AJAX dưới dạng cây chứ không phải dưới dạng văn bản thuần túy
- 17. Cách trả về định dạng ngày tháng cụ thể dưới dạng JSON trong Grails?
- 18. Gạch dưới dưới dạng biến JavaScript?
- 19. Delphi - dưới dạng
- 20. CGPath dưới dạng chuỗi
- 21. Các giá trị NaN tuần tự hóa thành JSON dưới dạng null trong JSON.NET
- 22. Làm cách nào để gửi yêu cầu POST dưới dạng JSON?
- 23. Symfony2 xuất ra bất kỳ bộ điều khiển HTML nào dưới dạng JSON
- 24. $ .jquery ajax dữ liệu trả về (json) hiển thị dưới dạng 'không xác định'
- 25. JSON xuất hiện dưới dạng các đối tượng unicode trong mẫu Jinja2
- 26. Làm thế nào để sắp xếp một mảng byte/uint8 dưới dạng mảng json trong Go?
- 27. REST API: Yêu cầu nội dung dưới dạng JSON hoặc dữ liệu POST đơn giản?
- 28. Trả về một mô hình Eloquent dưới dạng JSON trong Laravel 4
- 29. Có thư viện đơn giản nào sẽ hiển thị đối tượng JSON dưới dạng cây không?
- 30. đối tượng cửa hàng JSON trong thuộc tính số liệu dưới dạng HTML jQuery
Điều này không hiệu quả đối với tôi. Trong lớp MutableType (đối tượng): def copy_value tăng ngoại lệ. def copy_value (self, value): "" "Unimplemented." "" nâng NotImplementedError() –
Tôi đã thay đổi nguồn và nó hoạt động nhưng tôi không cảm thấy thoải mái về vấn đề bảo trì. –
Câu trả lời hay ... Cũng lưu ý rằng PostgreSQL hỗ trợ loại JSON. Điều này có vẻ hứa hẹn - nó giống như ví dụ của bạn, nhưng sẽ sử dụng loại JSON PostgreSQL nếu có. [sqlalchemy-utils JSONType] (http://sqlalchemy-utils.readthedocs.org/en/latest/_modules/sqlalchemy_utils/types/json.html) – hangtwenty