【问题标题】:Postgresql Json column not saving utf-8 characterPostgresql Json 列不保存 utf-8 字符
【发布时间】:2019-10-18 04:49:12
【问题描述】:

您好,我正在尝试使用 sqlalchemy 和 python 请求将从 api 获得的数据保存到我的 postgresql 中的 Json 列中。

r = requests.get(api)

content = r.content

data = json.loads(content)

crawl_item = {}
crawl_item = session.query(CrawlItem).filter_by(site_id=3, href=list_id).first()
crawl_item.description = data['ad']['body']
crawl_item.meta_data = {}
crawl_item.meta_data["ward"] = data['ad_params']['ward']['value']

try:
      session.commit()
except:
      session.rollback()
      raise
finally:
      ret_id = crawl_item.id
      session.close()

我的模特:

class CrawlItem(Base):
    ...
    description = Column(Text)
    meta_data = Column(postgresql.JSON)

我想得到 ward 的值:

"ward": {
      "id": "ward",
      "value": "Thị trấn Trạm Trôi",
      "label": " Phường, thị xã, thị trấn"
    }

我已经将我的 postgresql 编码为 utf-8,因此其他不是 json 列 (description = Column(Text)) 的字段通常保存 utf-8 字符,只有我的 json 列数据不被解码:

{ 
   "ward":"Th\u1ecb tr\u1ea5n Tr\u1ea1m Tr\u00f4i"
}

描述栏:

元数据列:

我曾尝试使用:

crawl_item.meta_data["ward"] = data['ad_params']['ward']['value'].decode('utf-8')

但病房数据没有保存

我不知道怎么了,希望有人能帮助我

编辑:

我用 psql 检查了数据并得到了这些:

描述栏:

元数据列:

似乎只有 meta_data json 列的字符有问题

【问题讨论】:

  • 你使用的是 Python 2 还是 Python 3?
  • 如果您使用psql 选择它,该值是什么样的?我想确定它是否以转义形式存储在数据库中。
  • @Ilja Everilä 我正在使用 python 3.6
  • 那么我的下一个问题是:填充列的 SQL 语句是什么?您可以在 PostgresSQL 中设置log_min_duration_statement = 0,然后记录语句和输入数据。然后你就知道转义是发生在 Python 中还是在数据库中。
  • 想一想,也许您在获取时没有使用正确的文本转换?您显示的最后一个 SELECT 语句就是一个例子;您选择了 Python 的 json 模块生成的“原始” JSON,其中包含转义数据。

标签: python postgresql sqlalchemy postgresql-json


【解决方案1】:

Sqlalchemy 在保存到数据库之前序列化 JSON 字段(请参阅urlurlurl)。

json_serializer = dialect._json_serializer or json.dumps

默认情况下,PostgreSQL 的方言使用json.dumpsjson.loads


当您使用文本列时,数据将按以下流程进行转换:

str -> bytes in utf-8 encoding

当您使用 PostgreSQL 方言的 JSON 列时,数据将按以下流程进行转换:

dict -> str with escaped non-ascii symbols -> bytes in utf-8 encoding

您可以使用 json_serializer 字段覆盖引擎配置中的序列化程序:

json_serializer=partial(json.dumps, ensure_ascii=False)

【讨论】:

    【解决方案2】:

    为您的 json 列使用“jsonb”数据类型或将“meta_data”字段转换为“jsonb”,如下所示:

    select meta_data::jsonb from your_table;
    

    【讨论】:

      猜你喜欢
      • 2019-08-08
      • 2019-01-31
      • 2017-05-14
      • 2018-01-26
      • 2014-10-13
      • 1970-01-01
      • 1970-01-01
      • 2012-12-19
      • 1970-01-01
      相关资源
      最近更新 更多