postgresql psycopg2插入python字典作为json

vh0rcniy  于 12个月前  发布在  PostgreSQL
关注(0)|答案(7)|浏览(113)

我想插入一个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(“导入产品(store_id,url,price,characteristics,color,dimensions)VALUES(%d,% s,% s,%d,%s)",(1,' http://www.google.com ','$20',thedictionary,' red ',' 8.5x11'))psycopg2.ProgrammingError:can't adapt type 'dict'
我不知道如何从这里开始。我在互联网上找不到任何关于如何做这种确切的事情,我是非常新的psycopg 2。

vsdwdz23

vsdwdz231#

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])

ijnw1ujt

ijnw1ujt2#

psycopg docs
注意你可以使用register_adapter()来将任何Python字典适配到JSON,无论是注册JSON还是任何子类或工厂创建一个兼容的适配器:
第一个月
这个设置是全局的,所以它不兼容类似的适配器,比如register_hstore()注册的适配器。JSON支持的任何其他对象都可以以同样的方式注册,但是这会破坏默认的适配规则,所以要小心不必要的副作用。
所以,在我的情况下,我所做的是:

from psycopg2.extras import Json
from psycopg2.extensions import register_adapter

register_adapter(dict, Json)

字符串
它就像一个魅力。

zbsbpyhn

zbsbpyhn3#

2023-12-25
目前,我更喜欢使用sqlalchemy将JSON数据插入PostgreSQL。

from sqlalchemy import create_engine
import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# create_engine
PGDATABASE='PGDATABASE'
PGHOST="192.168.100.100"
PGUSER="PGUSER"
PGPASSWORD="PGPASSWORD"
PGPORT='5432'
pg_engine = create_engine(f'postgresql+psycopg2://{PGUSER}:{PGPASSWORD}@{PGHOST}:{PGPORT}/{PGDATABASE}')

# create test table
with pg_engine.connect() as conn:
    sql = '''
    BEGIN;
    -- DROP TABLE IF EXISTS url_test;
    CREATE TABLE url_test (
        "id" Serial, 
        "log_data" json,
        "cat_name" text,
        "created_at" timestamptz default now()
    );
    COMMIT;
    '''
    conn.execute(sql)
    logging.info("url_test created")

# 2023-12-14 sqlalchemy==2.0  not work 
# pip install --upgrade 'pandas<1.4' 'sqlalchemy<1.4' is ok
with pg_engine.connect() as conn:
    item = {
        'log_data': '{"abc":1, "de":null}',
        'cat_name': "demo-10%-'a",
        'created_at' : '2023-07-09',
    }
    tbl_name = 'src.url_test'
    sql = f'''
    INSERT INTO {tbl_name} (log_data, cat_name)
    VALUES (%(log_data)s, %(cat_name)s)
    ''' 
    conn.execute(sql, **item)
    logging.info("PG DUMP")

字符串
答案在2020年。
您可以使用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)


有关更多信息,您可以查看官方文档。

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.

dy1byipe

dy1byipe4#

从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

q3aa0525

q3aa05255#

只需将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:[email protected]: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')


的数据

9wbgstp7

9wbgstp76#

首先,这个错误意味着你试图将一个dict值推入一个不能接受它的列类型(TEXT等)。
接受的解决方案是正确的,将其从JSON/dict -> string转换为存储它。
但是,有一种列类型可以接受它:JSON
我建议首先创建一个JSON字段,以保持类似于dict的对象。原因是:
1.你可以简单地将dict按原样推送到DB w/o json.dumps或其他转换(因为记住,当你推时-你需要json.dumps,但当你稍后在python中读取它时,你需要json.loads(从string -> dict转换回来)。
1.你可以在一个真实的JSON列中查询它的内容,当它是一个字符串时你不能这样做。
https://www.postgresqltutorial.com/postgresql-json/
因此,当创建列时,我建议使用默认值{} vs NULL:

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

字符串

kb5ga3dv

kb5ga3dv7#

是否有特别的原因让你想把每个键作为自己的列?Postgres允许你在包含有效JSON或JSONB的单个列中执行直接查询操作
这意味着您可以简单地创建一个具有ID(主键)和元数据的2列DB,然后执行查询,例如:

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

字符串
Here对你来说是一个很好的资源。

相关问题