El ->
y ->>
Los operadores se introdujeron en SQLite versión 3.38.0, que se lanzó el 22 de febrero de 2022. Ambos operadores se utilizan para extraer subcomponentes de JSON. Pero hay una sutil diferencia entre ellos.
La diferencia
La diferencia entre estos operadores es la siguiente:
- El
->
el operador siempre devuelve un JSON representación del subcomponente especificado - El
->>
operador siempre devuelve un SQL representación del subcomponente especificado
Ejemplo
Aquí hay un ejemplo que ilustra la diferencia entre estos dos operadores:
SELECT
'{ "name" : "Wag", "type" : "Dog" }' -> '$.type' AS "->",
'{ "name" : "Wag", "type" : "Dog" }' ->> '$.type' AS "->>";
Resultado:
+-------+-----+ | -> | ->> | +-------+-----+ | "Dog" | Dog | +-------+-----+
Podemos ver que ->
devolvió el valor entre comillas dobles mientras que ->>
no lo hizo.
Eso es porque ->
devolvió una representación JSON del valor y ->>
devolvió una representación SQL.
Números
Aquí hay un ejemplo que usa números:
SELECT
'{ "age" : 10 }' -> '$.age' AS "->",
'{ "age" : 10 }' ->> '$.age' AS "->>";
Resultado:
+----+-----+ | -> | ->> | +----+-----+ | 10 | 10 | +----+-----+
Esto es lo que sucede cuando usamos typeof()
función para obtener el tipo SQL:
SELECT
typeof('{ "age" : 10 }' -> '$.age') AS "->",
typeof('{ "age" : 10 }' ->> '$.age') AS "->>";
Resultado:
+------+---------+ | -> | ->> | +------+---------+ | text | integer | +------+---------+
Sin embargo, si usamos json_type()
, obtendremos el tipo JSON:
SELECT
json_type('{ "age" : 10 }' -> '$.age') AS "->",
json_type('{ "age" : 10 }' ->> '$.age') AS "->>";
Resultado:
+---------+---------+ | -> | ->> | +---------+---------+ | integer | integer | +---------+---------+
Aquí hay un ejemplo que usa un número real:
SELECT
typeof('{ "age" : 1.2 }' -> '$.age') AS "->",
typeof('{ "age" : 1.2 }' ->> '$.age') AS "->>";
Resultado:
+------+------+ | -> | ->> | +------+------+ | text | real | +------+------+
Y con json_type()
:
SELECT
json_type('{ "age" : 1.2 }' -> '$.age') AS "->",
json_type('{ "age" : 1.2 }' ->> '$.age') AS "->>";
Resultado:
+------+------+ | -> | ->> | +------+------+ | real | real | +------+------+
Valores nulos
Si el documento JSON contiene null
, luego ->
devolverá la representación JSON de nulo y ->>
simplemente devolverá un valor nulo.
Aquí hay un ejemplo para demostrar lo que quiero decir:
SELECT
'{ "name" : "Wag", "type" : null }' -> '$.type' AS "->",
'{ "name" : "Wag", "type" : null }' ->> '$.type' AS "->>";
Resultado:
+------+-----+ | -> | ->> | +------+-----+ | null | | +------+-----+
De forma predeterminada, la interfaz de línea de comandos (CLI) de SQLite devuelve la cadena vacía cada vez que se devuelve un valor nulo. Entonces podemos ver en nuestro ejemplo que ->
devolvió el valor JSON real nulo, mientras que ->>
devolvió un valor nulo real.
Para demostrar esto aún más, podemos configurar nuestro .nullvalue
a algo que no sea la cadena vacía:
.nullvalue n/a
Ahora ejecutemos la consulta anterior de nuevo:
SELECT
'{ "name" : "Wag", "type" : null }' -> '$.type' AS "->",
'{ "name" : "Wag", "type" : null }' ->> '$.type' AS "->>";
Resultado:
+------+-----+ | -> | ->> | +------+-----+ | null | n/a | +------+-----+
Esta vez n/a
se emitió para el ->>
operador en lugar de la cadena vacía.
Y esto es lo que sucede cuando pasamos la salida a typeof()
y json_type()
funciones:
SELECT
typeof('{ "name" : "Wag", "type" : null }' -> '$.type') AS "->",
typeof('{ "name" : "Wag", "type" : null }' ->> '$.type') AS "->>";
SELECT
json_type('{ "name" : "Wag", "type" : null }' -> '$.type') AS "->",
json_type('{ "name" : "Wag", "type" : null }' ->> '$.type') AS "->>";
Resultado:
+------+------+ | -> | ->> | +------+------+ | text | null | +------+------+ +------+-----+ | -> | ->> | +------+-----+ | null | n/a | +------+-----+
Una alternativa:json_extract()
Otra forma de extraer valores de un documento JSON en SQLite es usar json_extract()
función. Esta función funciona de forma ligeramente diferente a ->
y ->>
en que el tipo de retorno depende del contexto.
El json_extract()
La función solo devuelve JSON si hay dos o más argumentos de ruta (porque el resultado es una matriz JSON) o si el argumento de ruta única hace referencia a una matriz u objeto.
Si solo hay un argumento de ruta y esa ruta hace referencia a un JSON nulo, una cadena o un valor numérico, entonces json_extract()
devuelve el valor SQL NULL, TEXT, INTEGER o REAL correspondiente.