2

I have this table in postgres

CREATE TABLE target (
    a json
)

Which I would like to insert data to from psycopg2 using

import psycopg2
import psycopg2.extras as extras

# a is list of list of dicts
a = [[{'a':1,'b':2}, {'d':3,'e':2}],
      [{'a':3,'b':1}, {'e':2,'f':6}]]

# convert a to list of tuples containing extras.Json objects
a = [(extras.Json(x),) for x in a]

# insert a to the database
query = ('WITH ins (a) AS '
         '(VALUES %s) '
         'INSERT INTO target (a) '
         'SELECT ins.a '
         'FROM ins;')

cursor = conn.cursor()

extras.execute_values(cursor, query, a)

However I get the error: column "a" is of type json but expression is of type text

This example is simplified to make the question clearer (which is why the example is using the WITH ins statement as I need to join a table to it. I would have thought that this should work but for some reason it doesn't. My suspicion is the problem is that I load it in to ins first and maybe it loads it as a text instead of json there by default for some reason.

How do I solve this?

1 Answer 1

1

Something like this:

CREATE TABLE target (
    a json
)

query = "INSERT INTO target VALUES %s"  

b = [[extras.Json(row)] for row in a] 
cur = con.cursor()
extras.execute_values(cur, query, b)
con.commit()

select * from target;
                  a                   
--------------------------------------
 [{"a": 1, "b": 2}, {"d": 3, "e": 2}]
 [{"a": 3, "b": 1}, {"e": 2, "f": 6}]

Simplified to just INSERT directly from the input values. I created them as a list as execute_values can take a sequence of sequences or a sequence of dictionaries(if using named parameters).

UPDATE:

query = ('WITH ins (a) AS '
         '(VALUES %s) '
         'INSERT INTO target (a) '
         'SELECT ins.a::json '
         'FROM ins;')


Sign up to request clarification or add additional context in comments.

3 Comments

Thank you so much for your answer. Unfortunately the WITH ins statement is necessary as I need to join a table to it. Maybe I oversimplified too much. Is there anyway to adjust your method to work the WITH ins ...
Am I correct in assumning that this solution would load the json as a text into ins and then cast it from text to json when selecting?
Yes, that is the case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.