8

I'm using Postgres 9.5 and I have a column ("info") of type 'json'... I'm trying to do this insert:

INSERT INTO table ( info )
VALUES (
  '{"entry":"((\+)[0-9]+)"}'
)

but I get this error:

ERROR:  invalid input syntax for type json
DETAIL:  Escape sequence "\+" is invalid.

It's interpreting \+ as an escape sequence but I actually want that as part of my value.

1
  • Please help get this where it belongs, and flag to migrate this to Database Administrators. Commented Apr 19, 2017 at 18:28

2 Answers 2

11

In general,

  • if you have keys and values use jsonb_build_object to construct the object
  • if you're writing a literal JSON object to cast from string, then it must be proper; a proper JSON string requires escaping \.

Explanation

PostgreSQL isn't quoting this: it's just the JSON implimentation following RFC 7159.

A string begins and ends with quotation marks. All Unicode characters may be placed within the quotation marks, except for the characters that must be escaped: quotation mark, reverse solidus, and the control characters (U+0000 through U+001F). [... ] So, for example, a string containing only a single reverse solidus character may be represented more compactly as "\\".

So it looks like this in the literal form.

CREATE TABLE tbl
AS
  SELECT '{"entry":"((\\+)[0-9]+)"}'::jsonb AS info;

Dollar-quoting in PostgreSQL requires no-escapes, but it will not help here,

Notice that inside the dollar-quoted string, single quotes can be used without needing to be escaped. Indeed, no characters inside a dollar-quoted string are ever escaped: the string content is always written literally. Backslashes are not special, and neither are dollar signs, unless they are part of a sequence matching the opening tag.

So this will not work because \+ is not a valid string in JSON. It would work if we were not using a json type though.

SELECT '{"key":"\"}'::jsonb;
ERROR:  invalid input syntax for type json
LINE 1: SELECT '{"key":"\"}'::jsonb;
               ^
DETAIL:  Token ""\"}" is invalid.
CONTEXT:  JSON data, line 1: {"key":"\"}

However, you can use to_jsonb() to JSON-escape the strings..

SELECT FORMAT( $${%s:%s}$$, to_jsonb(k), to_jsonb(v) )::jsonb
FROM ( VALUES
  ('key', '\' )
) AS t(k,v);

But, even this is a bad idea because if you have the keys and values you can use json_build_object,

SELECT jsonb_build_object( k, v )
FROM ( VALUES
  ('key', '\' )
) AS t(k,v);
Sign up to request clarification or add additional context in comments.

2 Comments

This works, as it will get escape the \, however... in the database column, I now have an extra \ for this entry ( i.e. ((\\+)[0-9]+) ) when I retrieve this data. Is there a way to have it return the original, unescaped value?
@Faybian See How to convert a json string to text?, if you need to access the value stored in the property value (info ->> 'entry' in your case). But if you retrieve the whole JSON (the info object, or the info -> 'entry' string), there is no "extra backslash", it's just the required escaping in the JSON value - which also has "extra quotes" around the string.
0

I had a similar problem, found an easy solution which will remove escape character present in the jsonb field.

select (jsonb_field_name #>> '{}')::jsonb from table_name

Now you can see the data in a cleaner way

1 Comment

See stackoverflow.com/q/27215216/1048572 for why and how this works. But this isn't really what the OP asked about here.

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.