psycopg2将python字典插入为json

时间:2015-08-03 20:37:04

标签: python postgresql dictionary psycopg2

我想将一个python字典作为json插入到我的postgresql数据库中(通过python和psycopg2)。

我有:

thedictionary = {'price money': '$1', 'name': 'Google', 'color': '', 'imgurl': 'http://www.google.com/images/nav_logo225.png', 'charateristics': 'No Description', 'store': 'google'}

cur.execute("INSERT INTO product(store_id, url, price, charecteristics, color, dimensions) VALUES (%d, %s, %s, %d, %s, %s)", (1,  'http://www.google.com', '$20', thedictionary, 'red', '8.5x11'))

它给出了错误消息:

  

cur.execute(" INSERT INTO产品(store_id,url,价格,特征,颜色,尺寸)VALUES(%d,%s,%s,%d,%s,%s)&#34 ;,(1,' http://www.google.com',' $ 20',thedictionary,' red',' 8.5x11') )       psycopg2.ProgrammingError:无法调整类型' dict'

我不知道如何从这里开始。 我在互联网上找不到关于如何做这种事情的事情,我对psycopg2很新。

7 个答案:

答案 0 :(得分:39)

cur.execute("INSERT INTO product(store_id, url, price, charecteristics, color, dimensions) VALUES (%s, %s, %s, %s, %s, %s)", (1,  'http://www.google.com', '$20', json.dumps(thedictionary), 'red', '8.5x11'))

这将解决您的问题。但是,您确实应该将键和值存储在各自独立的列中。要检索字典,请执行以下操作:

cur.execute('select charecteristics from product where store_id = 1')
dictionary = json.loads(cur.fetchone()[0])

答案 1 :(得分:5)

您可以使用psycopg2.extras.Json将dict转换为postgre接受的json。

from psycopg2.extras import Json

thedictionary = {'price money': '$1', 
'name': 'Google', 'color': '', 'imgurl': 'http://www.google.com/images/nav_logo225.png', 'charateristics': 'No Description', 'store': 'google'}

item ={
    "store_id":1,
    "url": 'http://www.google.com', 
    "price":'$20', 
    "charecteristics":Json(thedictionary), 
    "color":'red', 
    "dimensions":'8.5x11'
}

def sql_insert(tableName, data_dict):
    '''
    INSERT INTO product (store_id,  url,  price,  charecteristics,  color,  dimensions)
    VALUES (%(store_id)s, %(url)s, %(price)s, %(charecteristics)s, %(color)s, %(dimensions)s );
    '''
    sql = '''
        INSERT INTO %s (%s)
        VALUES (%%(%s)s );
        '''   % (tableName, ',  '.join(data_dict),  ')s, %('.join(data_dict))
    return sql

tableName = 'product'
sql = sql_insert(tableName, item)

cur.execute(sql, item)

有关更多信息,请参见the office document

class psycopg2.extras.Json(adapted, dumps=None)

    An ISQLQuote wrapper to adapt a Python object to json data type.

    Json can be used to wrap any object supported by the provided dumps function. If none is provided, the standard json.dumps() is used (simplejson for Python < 2.6; getquoted() will raise ImportError if the module is not available).

    dumps(obj)
    Serialize obj in JSON format.

    The default is to call json.dumps() or the dumps function provided in the constructor. You can override this method to create a customized JSON wrapper.

答案 2 :(得分:2)

来自psycopg docs

  

请注意,您可以使用register_adapter()将任何Python词典改编为JSON,可以注册Json或任何子类或在工厂创建兼容的适配器:

     

psycopg2.extensions.register_adapter(dict, psycopg2.extras.Json)

     

尽管此设置是全局的,所以它与类似的适配器(例如由register_hstore()注册的适配器)不兼容。 JSON支持的任何其他对象都可以用相同的方式注册,但这会破坏默认的适应规则,因此请注意不要的副作用。

所以,就我而言,我所做的是:

from psycopg2.extensions import register_adapter

register_adapter(dict, Json)

它就像一种魅力。

答案 3 :(得分:1)

只需将dict类型转换为json_str,请使用json.dumps(adict)

import pandas as pd
import json
import psycopg2
from sqlalchemy import create_engine
engine_nf = create_engine('postgresql+psycopg2://user:password@192.168.100.120:5432/database')
sql_read = lambda sql: pd.read_sql(sql, engine_nf)
sql_execute = lambda sql: pd.io.sql.execute(sql, engine_nf)

sql = '''
CREATE TABLE if not exists product (
    store_id  int
    , url  text
    , price text
    , charecteristics json
    , color text
    , dimensions text
)
'''
_ = sql_execute(sql)

thedictionary = {'price money': '$1', 'name': 'Google', 
    'color': '', 'imgurl': 'http://www.google.com/images/nav_logo225.png', 
    'charateristics': 'No Description', 
    'store': 'google'}

sql = '''
INSERT INTO product(store_id, url, price, charecteristics, color, dimensions) 
VALUES (%d, '%s', '%s', '%s', '%s', '%s')
''' % (1, 'http://www.google.com', '$20', 
       json.dumps(thedictionary), 'red', '8.5x11')

sql_execute(sql)

sql = '''
select * 
from product
'''
df = sql_read(sql)
df
    #   store_id    url price   charecteristics color   dimensions
    # 0 1   http://www.google.com   $20 {'price money': '$1', 'name': 'Google', 'color...   red 8.5x11

charecteristics = df['charecteristics'].iloc[0]
type(charecteristics)
    # dict

实际上,我喜欢将数据转储到postgres的另一种方法。

import io
import csv
def df2db(df_a, table_name, engine):
    output = io.StringIO()
    # ignore the index
    df_a.to_csv(output, sep='\t', index = False, header = False, quoting=csv.QUOTE_NONE)
    output.getvalue()
    # jump to start of stream
    output.seek(0)

    #engine ---- from sqlalchemy import create_engine
    connection = engine.raw_connection() 
    cursor = connection.cursor()
    # null value become ''
    cursor.copy_from(output,table_name,null='')
    connection.commit()
    cursor.close()


df = sql_read('select * from product')
type(df.charecteristics.iloc[0])
df.charecteristics = df.charecteristics.map(json.dumps)

# dump pandas DataFrame to postgres
df2db(df, 'product', engine_nf)
df_end = sql_read('select * from product')

enter image description here

答案 4 :(得分:1)

首先,该错误意味着您试图将 dict 值推送到无法接受它的列类型(TEXT 等 ..)

接受的解决方案是将其从 JSON/dict 转换 -> 字符串以存储它。

但是,有一个可以接受它的列类型:JSON

我建议首先创建一个 JSON 字段以保留类似 dict 的对象。原因是:

  1. 您可以简单地将字典按原样推送到数据库,无需 json.dumps 或其他转换(因为请记住,当您推送时 - 您需要 json.dumps 但是当您阅读 稍后在 python 中你需要 json.loads(从字符串转换回来 -> dict)。
  2. 您可以在真正的 JSON 列中查询它的内容,这是字符串时无法做到的。

https://www.postgresqltutorial.com/postgresql-json/

因此,在创建列时,我建议将默认值设为 {} 与 NULL:

CREATE TABLE my_table (
   ...
   my_json_col JSON default '{}'::JSON
   ...
)

答案 5 :(得分:0)

从 psycopg2 2.5 版开始,您可以使用 Json 适配器。

<块引用>

Psycopg 可以使 Python 对象适应 PostgreSQL json 和 jsonb 类型。对于 PostgreSQL 9.2 及以下版本的适配,可开箱即用。

from psycopg2.extras import Json
curs.execute("insert into mytable (jsondata) values (%s)", [ Json({'a': 100}) ] )

有关更多信息,请参阅文档: https://www.psycopg.org/docs/extras.html#json-adaptation

答案 6 :(得分:-1)

您是否有特定的原因要将每个键作为自己的列? Postgres使您可以在包含有效JSON或JSONB的单个列中执行直接查询操作

这意味着您可以简单地创建一个具有ID(主键)和元数据的2列DB,然后执行诸如以下查询:

SELECT * FROM users WHERE metadata @> '{"key": "value"}';

Here是您的理想资源。