Postgres: Como converter uma string json em texto?

91

O valor Json pode consistir em um valor de string. por exemplo.:

postgres=# SELECT to_json('Some "text"'::TEXT);
     to_json
-----------------
 "Some \"text\""

Como posso extrair essa string como um valor de texto postgres?

::TEXTnão funciona. Ele retorna json entre aspas, não a string original:

postgres=# SELECT to_json('Some "text"'::TEXT)::TEXT;
     to_json
-----------------
 "Some \"text\""

Obrigado.

PS Estou usando PostgreSQL 9.3

E79ene
fonte
stackoverflow.com/q/19414361/562459 pode ajudar. Pode não.
Mike Sherrill 'Cat Recall'
Problema semelhante com matriz de strings, stackoverflow.com/q/45243186/287948
Peter Krauss

Respostas:

54

Não há como no PostgreSQL desconstruir um objeto JSON escalar. Assim, como você aponta,

select  length(to_json('Some "text"'::TEXT) ::TEXT);

é 15,

O truque é converter o JSON em uma matriz de um elemento JSON e, em seguida, extrair esse elemento usando ->>.

select length( array_to_json(array[to_json('Some "text"'::TEXT)])->>0 );

retornará 11.

Robert M. Lefkowitz
fonte
8
É uma pena que json_extract_path_text()não possa fazer referência ao elemento raiz (AFAIK).
Erwin Brandstetter
3
curiosamente, houve uma discussão de brainstorming, aparentemente de volta ao estágio de design da API em 2012, em que uma função from_jsonfoi proposta, mas não implementada wiki.postgresql.org/wiki/JSON_API_Brainstorm
nikola
143

Em 9.4.4, usar o #>>operador funciona para mim:

select to_json('test'::text) #>> '{}';

Para usar com uma coluna de tabela:

select jsoncol #>> '{}' from mytable;
Ian Timothy
fonte
2
Parece ser a solução mais simples no Postgres 9.4. No entanto, não funciona para 9.3.
e79ene de
2
@hasen O OP afirma que ele está tentando extrair texto de um valor JSON e to_json(...)é simplesmente uma maneira fácil de criar um valor JSON para trabalhar como exemplo em uma instrução curta de uma linha. Certamente você o substituiria pelo nome de uma coluna JSON se estivesse consultando uma tabela conforme descreve. Além disso, para esclarecer um ponto de confusão potencial, seu elenco (...)::texté redundante, pois o #>>operador retorna texto por definição (e é a razão para usar o operador em primeiro lugar). Você pode manter os parênteses, mas descartar o gesso ::text.
Ian Timothy
1
Alguém poderia explicar o que #>>e o que '{}'está fazendo? Eu não consigo entender isso e nenhum dos termos é amigável ao Google. Essa resposta resolveu meu problema, só quero saber por quê.
valadil
1
@valadil A documentação do #>>operador está aqui .
Ian Timothy
1
@valadil Nesse caso, há um objeto JSON de nível superior ou raiz text. Pode parecer uma string, mas é um objeto JSON. Para converter esse objeto de JSON em texto, use o #>>operador. Mas esse operador precisa que você especifique um caminho. O caminho para esse objeto raiz é {}. Isso SELECT '"test"'::jsonb #>> '{}'significa "pegar o objeto no caminho da raiz e convertê-lo em texto".
Ian Timothy,
3

O Sr. Curioso também estava curioso sobre isso. Além do #>> '{}'operador, em 9.6+ pode-se obter o valor de uma string jsonb com o ->>operador:

select to_jsonb('Some "text"'::TEXT)->>0;
  ?column?
-------------
 Some "text"
(1 row)

Se um tiver um valor json, a solução é converter primeiro em jsonb:

select to_json('Some "text"'::TEXT)::jsonb->>0;
  ?column?
-------------
 Some "text"
(1 row)
Senhor curioso
fonte
1

- >> funciona para mim.

versão postgres:

<postgres.version>11.6</postgres.version>

Inquerir:

select object_details->'valuationDate' as asofJson, object_details->>'valuationDate' as asofText from MyJsonbTable;

Resultado:

  asofJson       asofText
"2020-06-26"    2020-06-26
"2020-06-25"    2020-06-25
"2020-06-25"    2020-06-25
"2020-06-25"    2020-06-25
Surinder
fonte
Obrigado por apontar, eu corrigi a versão acima
Surinder
0

Uma maneira fácil de fazer isso:

SELECT  ('[' || to_json('Some "text"'::TEXT) || ']')::json ->> 0;

Basta converter a string json em uma lista json

Zhemin Zhou
fonte