Postgres: ¿Cómo convertir una cadena json en texto?

93

El valor de JSON puede consistir en un valor de cadena. p.ej.:

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

¿Cómo puedo extraer esa cadena como un valor de texto de postgres?

::TEXTno funciona. Devuelve json entre comillas, no la cadena original:

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

Gracias.

PD: estoy usando PostgreSQL 9.3

e79ene
fuente
stackoverflow.com/q/19414361/562459 podría ayudar. Tal vez no.
Mike Sherrill 'Cat Recall'
Problema similar con la matriz de cadenas, stackoverflow.com/q/45243186/287948
Peter Krauss

Respuestas:

58

No hay forma en PostgreSQL de deconstruir un objeto JSON escalar. Por lo tanto, como señala,

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

tiene 15 años,

El truco es convertir el JSON en una matriz de un elemento JSON, luego extraer ese elemento usando ->>.

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

volverá 11.

Robert M. Lefkowitz
fuente
8
Es una pena que json_extract_path_text()no pueda hacer referencia al elemento raíz (AFAIK).
Erwin Brandstetter
3
Curiosamentefrom_json
Nikola
147

En 9.4.4, el uso del #>>operador funciona para mí:

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

Para usar con una columna de tabla:

select jsoncol #>> '{}' from mytable;
Ian Timothy
fuente
2
Parece ser la solución más simple en Postgres 9.4. Sin embargo, no funciona para 9.3.
e79ene
2
@hasen El OP afirma que está tratando de extraer texto de un valor JSON y to_json(...)es simplemente una forma fácil de crear un valor JSON para trabajar como ejemplo en una declaración corta de una línea. Ciertamente, lo reemplazaría con el nombre de una columna JSON si estuviera consultando una tabla como la describe. Además, para aclarar un punto de posible confusión, su transmisión (...)::textes redundante ya que el #>>operador devuelve texto por definición (y es la razón para usar el operador en primer lugar). Puede mantener los paréntesis pero quitar el yeso ::text.
Ian Timothy
1
Podría alguien explicar qué #>>y '{}'lo están haciendo? No puedo seguir esto y ninguno de los términos es compatible con Google. Esta respuesta solucionó mi problema, solo quiero saber por qué.
valadil
1
@valadil La documentación para el #>>operador está aquí .
Ian Timothy
1
@valadil En este caso, hay un objeto JSON de nivel superior o raíz text. Puede parecer una cadena, pero es un objeto JSON. Para convertir ese objeto de JSON a texto, use el #>>operador. Pero ese operador necesita que especifiques una ruta. La ruta a ese objeto raíz es {}. Entonces SELECT '"test"'::jsonb #>> '{}'significa "obtener el objeto en la ruta raíz y convertirlo en texto".
Ian Timothy
3

El Sr. Curious también sentía curiosidad por esto. Además del #>> '{}'operador, en 9.6+ se puede obtener el valor de una cadena jsonb con el ->>operador:

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

Si uno tiene un valor json, entonces la solución es lanzarlo a jsonb primero:

select to_json('Some "text"'::TEXT)::jsonb->>0;
  ?column?
-------------
 Some "text"
(1 row)
Señor curioso
fuente
0

Una forma sencilla de hacer esto:

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

Simplemente convierta la cadena json en una lista json

Zhemin Zhou
fuente
0

- >> funciona para mí.

versión de postgres:

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

Consulta:

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

Salida:

  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
fuente
Gracias por señalar, corrigí la versión anterior
Surinder
La pregunta original es cómo obtener el valor de una cadena JSON como texto con (sin clave de objeto). Esta respuesta es solo la diferencia entre ->y ->>cuando se usa una tecla. Vea esta respuesta o esta respuesta .
Ian Timothy