WordPress está eliminando las barras invertidas de escape de cadenas JSON en post_meta

25 may 2012, 23:39:35
Vistas: 15.4K
Votos: 19

Pensé que estaba facilitando mi vida y siendo consciente del futuro al guardar cierto contenido como fragmentos JSON en campos post_meta personalizados. Desafortunadamente, WordPress no está de acuerdo y está haciendo mi vida increíblemente difícil.

Tengo una cadena JSON que básicamente se ve así. Esto es solo una parte, y la cadena de comentarios son solo algunas entidades unicode de ejemplo. Todo se genera con json_encode.

{
    "0": {
        "name": "Chris",
        "url": "testdomain.com",
        "comment": "\u00a5 \u00b7 \u00a3 \u00b7 \u20ac \u00b7 \u00b7 \u00a2 \u00b7 \u20a1 \u00b7 \u20a2 \u00b7 \u20a3 \u00b7 \u20a4 \u00b7 \u20a5 \u00b7 \u20a6 \u00b7 \u20a7 \u00b7 \u20a8 \u00b7 \u20a9 \u00b7 \u20aa \u00b7 \u20ab \u00b7 \u20ad \u00b7 \u20ae \u00b7 \u20af \u00b7 \u20b9"
    }
}

Desafortunadamente, después de guardarlo con update_post_meta, sale así:

{
    "0": {
        "name": "Chris",
        "url": "testdomain.com",
        "comment": "u00a5 u00b7 u00a3 u00b7 u20ac u00b7 u00b7 u00a2 u00b7 u20a1 u00b7 u20a2 u00b7 u20a3 u00b7 u20a4 u00b7 u20a5 u00b7 u20a6 u00b7 u20a7 u00b7 u20a8 u00b7 u20a9 u00b7 u20aa u00b7 u20ab u00b7 u20ad u00b7 u20ae u00b7 u20af u00b7 u20b9"
    }
}

Y al eliminar las barras invertidas, no se puede hacer json_decode para volver a convertirlo en contenido útil.

¿Alguna idea de por qué WordPress podría estar haciendo esto y si hay alguna manera de evitarlo? No puedo usar la bandera JSON_UNESCAPED_UNICODE porque esta es una instalación de PHP 5.3.x, y ya intenté codificar con htmlentities antes de pasar el contenido a json_encode, pero eso solo captura un pequeño subconjunto de entidades UTF-8.

¡Gracias de antemano!

(EDIT: Por cierto, sé que podría simplemente guardar un array directamente en post_meta y se serializaría y ocurriría la magia, pero me gusta la idea de tener los datos almacenados como JSON. Si no hay una solución fácil y elegante, cederé, ¡pero realmente espero que haya una solución fácil y elegante!)

0
Todas las respuestas a la pregunta 8
5
36

¡Existe una manera elegante de manejar esto!

Pasa la cadena codificada en JSON a través de wp_slash(). Esta función escapará la barra diagonal inicial de cada carácter Unicode codificado, lo que evitará que update_metadata() los elimine.

9 ene 2014 19:20:40
Comentarios

Esta es una solución alternativa para un error grave de WordPress. ¡Muchas gracias!

netAction netAction
7 jun 2017 10:18:55

Esta debería ser la respuesta aceptada. Tuve problemas con contenido importado desde GitHub a través de wp_insert_post donde esto era un problema importante que eliminaba barras invertidas de muestras de código. Pasar la cadena por wp_slash antes de enviarla a wp_insert_post solucionó el problema. ¡Gracias!

Matt Keys Matt Keys
17 nov 2017 21:21:05

Esto sigue siendo útil incluso hoy, perdí horas y horas buscando una solución alternativa para esto sin ninguna pista hasta que encontré esto. Si quieres añadir esta respuesta a mi pregunta aquí: https://stackoverflow.com/questions/61091853/wordpress-breaking-unicodes-when-saving-data la marcaré como la respuesta correcta. ¡Muchísimas gracias!

Jaypee Jaypee
8 abr 2020 07:02:54

¿Quién hubiera pensado que una publicación de 8 años podría ayudarme? Tenía problemas al guardar bloques serializados (Gutenberg) con atributos codificados en JSON a los que se les eliminaban las barras invertidas. Ejecutar la salida de serialize_block a través de wp_slash solucionó el problema.

Wouter van Vliet Wouter van Vliet
5 abr 2021 16:47:09

Diez años después, me encontré con el mismo problema usando wp_insert_post(), y esto me salvó el día. ¡Gracias!

Saulo Padilha Saulo Padilha
11 jun 2024 01:08:23
3
11

Parece que no hay forma de evitarlo.

La función update_metadata(), que es finalmente responsable de guardar los metadatos, ejecuta explícitamente un stripslashes_deep() sobre el valor del meta. Esta función incluso eliminará las barras invertidas de los elementos de un arreglo, si el valor fuera un arreglo.

Hay un filtro que se ejecuta DESPUÉS de eso llamado sanitize_meta, al cual podrías engancharte. Pero en ese punto, tus barras invertidas ya han sido eliminadas, por lo que no puedes determinar de manera confiable dónde necesitaban volver a agregarse (o al menos, no sé cómo podrías distinguir entre comillas legítimas de delimitadores JSON versus partes de valores).

No puedo decir por qué hace esto, pero lo hace. Probablemente porque eventualmente se ejecuta a través de wpdb->update, que necesita las cadenas sin escapar.

Como temías, probablemente sea mejor simplemente almacenar el valor como un arreglo, que se serializará (como dijiste). Si lo quieres como JSON más tarde, puedes simplemente pasarlo por json_encode().

26 may 2012 00:18:44
Comentarios

Tenía miedo de eso, pero es bueno saber por qué está sucediendo. ¡Muchas gracias por la rápida respuesta!

Chris Van Patten Chris Van Patten
26 may 2012 00:33:10

Esto no es cierto, mira otras respuestas :)

jave.web jave.web
6 mar 2015 16:51:07

@jave.web Es cierto que no puedes evitar que update_metadata() aplique strip slashes a tu cadena. Las otras respuestas proporcionan soluciones (muy inteligentes) para esencialmente "escapar doblemente" tu cadena, de modo que el stripping inevitable elimine esas barras adicionales pero deje intactas tus barras originales. Personalmente, todavía diría que la forma "elegante" de manejar esto es simplemente almacenar los datos en un array, lo que no requiere ningún manejo especial ni pre-formateo. Luego conviértelo a json si y cuando lo necesites. Pero eso es solo mi preferencia.

MathSmath MathSmath
6 may 2015 21:36:28
1

Puedes engañar a WordPress con algo como esto:

$cleandata = str_replace('\\', '\\\\', json_encode($customfield_data, true));

Esta es una solución fácil y *elegante*...

1 ago 2012 13:36:28
Comentarios

+1 Esto funcionó para mi situación. Era un poco diferente a lo del OP, pero similar.

Adam Spriggs Adam Spriggs
1 ago 2018 14:43:16
0

Esta función realiza la transformación usando preg_replace:

function preg_replace_add_slash_json($valor) {
    return preg_replace('/(u[0-9a-fA-F]{4})/i', '\\\$1', $valor);
}

Antes de cada secuencia "uXXXX" (X=0..F, hexadecimal) añade una barra invertida. Antes de enviar a la base de datos, llama a esta función.

19 ene 2017 12:04:27
0

Para cualquiera que todavía tenga problemas para guardar una cadena Unicode codificada en JSON mediante wp_update_post, lo siguiente funcionó para mí. Encontrado en class-wp-rest-posts-controller.php

// convierte el objeto de publicación en un array, de lo contrario wp_update_post esperará entrada sin escapar.
wp_update_post( wp_slash( (array) $my_post ) ); 

Aquí hay un ejemplo:

$objectToEncodeToJson = array(
  'mi_clave_personalizada' => '<div>Aquí hay HTML que se convertirá a Unicode en la base de datos.</div>'
);

$postContent = json_encode($objectToEncodeToJson,JSON_HEX_TAG|JSON_HEX_QUOT);

$my_post = array(
  'ID'           => $yourPostId,
  'post_content' => $postContent
);

wp_update_post( wp_slash( (array) $my_post ) );
8 mar 2019 22:38:58
0

Una forma interesante de solucionar esto es codificando en base64, como se muestra en el siguiente ejemplo.

$data = Array(0 => array('name' => 'chris' , 'URL' => "hello.com"));

$to_json = json_encode($data);

echo $to_json  . "<br />";
// muestra [{"name":"chris","URL":"hello.com"}] 

$to_base64 =  base64_encode($to_json);

Echo $to_base64 . "<br />";
// muestra W3sibmFtZSI6ImNocmlzIiwiVVJMIjoiaGVsbG8uY29tIn1d

$back_to_json =  base64_decode($to_base64);

Echo $back_to_json . "<br />";
// muestra [{"name":"chris","URL":"hello.com"}]

$back_to_aray = json_decode($back_to_json);

print_r($back_to_aray) ;
// muestra Array ( [0] => stdClass Object ( [name] => chris [URL] => hello.com ))
18 jun 2013 14:34:16
0

Sé que esta es una pregunta antigua, pero todavía es un problema que afecta a los desarrolladores hoy en día. Así que como referencia, aquí hay un buen hilo del rastreador de problemas del núcleo de WordPress que encontré informativo: https://core.trac.wordpress.org/ticket/21767

21 may 2024 14:54:55
1
-1

Puedes utilizar la función de WordPress stripslashes_deep().

<?php stripslashes_deep($your_json);?>

Para referencia visita aquí

25 ene 2017 09:49:31
Comentarios

BARBJANE's todavía se envía desde WordPress como BARBJANE\'s a menos que me esté perdiendo algo aquí...

Si8 Si8
10 abr 2018 23:38:59