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

11

Pensé que me estaba haciendo la vida más fácil y estaba consciente del futuro al guardar algunos contenidos como bits de JSON en campos personalizados post_meta. Desafortunadamente, WordPress no está de acuerdo y está haciendo mi vida increíblemente difícil.

Tengo una cadena JSON que se ve esencialmente así. Esto es solo un bit, y la cadena de comentarios son solo algunas entidades unicode ficticias. 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 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 con las barras eliminadas, no se puede json_decodevolver a contenido útil.

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

¡Gracias por adelantado!

(EDITAR: FWIW, sé que podría guardar una matriz directamente en post_meta y se serializaría y ocurriría magia, pero me gusta la idea de tener los datos almacenados como JSON. Si no hay una solución fácil y elegante voy a la cueva, pero estoy mucho esperando que hay es una solución fácil, elegante!)

Chris Van Patten
fuente

Respuestas:

8

Parece que no hay forma de evitarlo.

La función update_metadata (), que en última instancia es responsable de guardar el meta, ejecuta explícitamente stripslashes_deep () en el metavalor. Esta función incluso eliminará barras de los elementos de la matriz, si el valor fuera una matriz.

Hay un filtro que se ejecuta DESPUÉS que se llama sanitize_meta, al que puede conectarse. Pero en ese momento, sus barras ya han sido eliminadas, por lo que no puede determinar de manera confiable dónde deben agregarse nuevamente (o al menos, no sé cómo distinguiría entre citar delimitadores JSON legítimos frente a bits de valores).

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

Como temía, probablemente sea mejor almacenar el valor como una matriz, que se serializará (como usted dijo). Si lo desea como JSON más tarde, puede ejecutarlo a través de json_encode ().

MathSmath
fuente
Tenía miedo de eso, pero es bueno saber por qué está sucediendo. Muchas gracias por la rápida respuesta!
Chris Van Patten
Esto no es cierto, ver otras respuestas :)
jave.web
@ jave.web Es cierto que no puede evitar que update_metadata () ejecute barras diagonales en su cadena. Las otras respuestas brindan soluciones (muy inteligentes) para esencialmente "doble escape" de su cadena, de modo que el despojo inevitable elimina esas barras adicionales pero deja intactas las barras originales. Personalmente, aún diría que la forma "elegante" de manejar esto es simplemente almacenar datos en una matriz, lo que no requiere un manejo especial o un formateo previo. Luego conviértalo a json si es necesario. Pero esa es solo mi preferencia.
MathSmath
25

¡Hay una manera elegante de manejar esto!

Pase la cadena codificada JSON wp_slash(). Esa función escapará a la barra inclinada inicial de cada carácter unicode codificado, lo que evitará update_metadata()despojarlos.

jkereako
fuente
Esta es una solución para un error grave de Wordpress. ¡Muchas gracias!
netAction
2
Esta debería ser la respuesta aceptada. Tuve problemas con el contenido que se importaba de GitHub a través de wp_insert_post, donde este era un problema importante al eliminar barras de muestras de código. Ejecutar la cadena a través de wp_slash antes de enviarla a través de wp_insert_post hizo el truco. ¡Gracias!
Matt Keys
Esto sigue siendo útil incluso hoy, perdí horas y horas para encontrar una solución para esto sin una sola pista hasta que encontré esto. Si desea agregar esta respuesta a mi pregunta aquí: stackoverflow.com/questions/61091853/… La marcaré como la respuesta correcta. Muchas gracias!
Jaypee
4

Puedes engañar a WordPress con algo como esto:

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

Esta es esa solución fácil * elegante * ...

drmartin
fuente
+1 Esto hizo el truco para mi situación. fue un poco diferente al OP, pero similar.
Adam Spriggs el
2

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

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

Antes de cada secuencia "uXXXX" (X = 0..F, hexadecimal) agrega barra invertida. Antes de enviar a DB, llame a esta función.

Florin Chis
fuente
1

Una forma interesante de evitar esto es codificar a base64, ver ejemplo a continuación.

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

$to_json = json_encode($data);

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

$to_base64 =  base64_encode($to_json);

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

$back_to_json =  base64_decode($to_base64);

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

$back_to_aray = json_decode($back_to_json);

print_r($back_to_aray) ;
//echos  Array ( [0] => stdClass Object ( [name] => chris [URL] => hello.com ))
David Allen
fuente
1

Para cualquiera que todavía tenga dificultades para guardar una cadena Unicode codificada con JSON a través de wp_update_post , lo siguiente funcionó para mí. Encontrado en class-wp-rest-posts-controller.php

// convert the post object to an array, otherwise wp_update_post will expect non-escaped input.
wp_update_post( wp_slash( (array) $my_post ) ); 

Aquí hay un ejemplo:

$objectToEncodeToJson = array(
  'my_custom_key' => '<div>Here is HTML that will be converted to Unicode in the db.</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 ) );
gbones
fuente
-1

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

<?php stripslashes_deep($your_json);?>

Para referencia visite aquí

Irfan Bin Hakim
fuente
BARBJANE'stodavía se envía desde WordPress como a BARBJANE\'smenos que me falte algo aquí ...
Si8