WordPress supprime les contre-obliques d'échappement des chaînes JSON dans post_meta

11

Je pensais que je rendais ma vie plus facile et que j'étais tourné vers l'avenir en enregistrant du contenu sous forme de morceaux de JSON dans des champs post_meta personnalisés. Malheureusement, WordPress n'est pas d'accord et rend ma vie incroyablement difficile.

J'ai une chaîne JSON qui ressemble essentiellement à ceci. Ce n'est qu'un bit, et la chaîne de commentaire n'est que quelques entités unicode factices. Le tout est généré avec 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"
    }
}

Malheureusement, après l'avoir enregistré avec update_post_meta, il apparaît comme ceci:

{
    "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"
    }
}

Et avec les barres obliques supprimées, il ne peut pas être json_decoderemis en contenu utile.

Des idées pourquoi WordPress pourrait faire cela, et s'il existe un moyen de l'éviter? Je ne peux pas utiliser l'indicateur JSON_UNESCAPED_UNICODE car il s'agit d'une installation PHP 5.3.x, et j'ai déjà essayé de coder avec htmlentitiesavant de transmettre le contenu json_encode, mais cela ne capture qu'un petit sous-ensemble d'entités UTF-8.

Merci d'avance!

(EDIT: FWIW, je sais que je pourrais simplement enregistrer un tableau directement dans post_meta et il serait sérialisé et la magie se produirait mais j'aime juste l'idée d'avoir les données stockées en JSON. S'il n'y a pas de solution simple et élégante Je vais céder, mais j'espère vraiment qu'il existe une solution simple et élégante!)

Chris Van Patten
la source

Réponses:

8

On dirait qu'il n'y a aucun moyen de l'éviter.

La fonction update_metadata (), qui est ultimement responsable de l'enregistrement de la méta, exécute explicitement un stripslashes_deep () sur la méta-valeur. Cette fonction supprimera même les barres obliques des éléments du tableau, si la valeur était un tableau.

Il y a un filtre qui est exécuté APRÈS et qui a appelé sanitize_meta, auquel vous pouvez vous connecter. Mais à ce stade, vos barres obliques ont déjà été supprimées, vous ne pouvez donc pas déterminer de manière fiable où elles doivent être ajoutées (ou du moins, je ne sais pas comment vous pourriez faire la différence entre citer des délimiteurs JSON légitimes par rapport aux bits des valeurs).

Je ne peux pas expliquer pourquoi il fait cela, mais c'est le cas. Probablement parce qu'il est finalement exécuté via wpdb-> update, qui nécessite que les chaînes ne soient pas échappées.

Comme vous le craigniez, vous feriez probablement mieux de simplement stocker la valeur sous forme de tableau, qui sera sérialisé (comme vous l'avez dit). Si vous le souhaitez en tant que JSON plus tard, vous pouvez simplement l'exécuter via json_encode ().

MathSmath
la source
J'en avais peur, mais c'est bon de savoir pourquoi cela se produit. Merci beaucoup pour la réponse rapide!
Chris Van Patten
Ce n'est pas vrai, voir les autres réponses :)
jave.web
@ jave.web Il est vrai que vous ne pouvez pas éviter que update_metadata () exécute des barres obliques sur votre chaîne. Les autres réponses fournissent des solutions de contournement (très intelligentes) pour essentiellement "double échapper" votre chaîne, de sorte que le décapage inévitable supprime ces barres obliques supplémentaires mais laisse intactes vos barres obliques d'origine. Personnellement, je dirais toujours que la façon "élégante" de gérer cela est de simplement stocker les données dans un tableau, ce qui ne nécessite aucune manipulation ou pré-formatage spécial. Ensuite, convertissez-le en json si et quand vous en avez besoin. Mais c'est juste ma préférence.
MathSmath
25

Il existe une manière élégante de gérer cela!

Passez la chaîne encodée JSON wp_slash(). Cette fonction échappera à la barre oblique principale de chaque caractère unicode codé, ce qui empêchera update_metadata()de les supprimer.

jkereako
la source
Il s'agit d'une solution de contournement pour un grave bug Wordpress. Merci beaucoup!
netAction
2
Ce devrait être la réponse acceptée. J'ai eu des problèmes avec le contenu importé de GitHub via wp_insert_post où c'était un problème majeur pour supprimer les barres obliques des exemples de code. L'exécution de la chaîne via wp_slash avant de l'envoyer via wp_insert_post a fait l'affaire. Merci!
Matt Keys
C'est toujours utile même aujourd'hui, j'ai perdu des heures et des heures pour trouver une solution à cela sans aucun indice jusqu'à ce que je trouve cela. Si vous souhaitez ajouter cette réponse à ma question ici: stackoverflow.com/questions/61091853/… Je la marquerai comme la bonne réponse. Merci beaucoup!
Jaypee
4

Vous pouvez tricher avec wordpress avec quelque chose comme ceci:

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

C'est que facile * solution élégante * ...

drmartin
la source
+1 Cela a fait l'affaire pour ma situation. c'était un peu différent de l'OP, mais similaire.
Adam Spriggs
2

Cette fonction effectue la transformation en utilisant preg_replace:

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

Avant chaque séquence "uXXXX" (X = 0..F, hexadécimal), il ajoute une barre oblique inverse. Avant de soumettre à DB, appelez cette fonction.

Florin Chis
la source
1

Un moyen intéressant de contourner cela est de coder en base64, voir l'exemple ci-dessous.

$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
la source
1

Pour tous ceux qui ont encore du mal à enregistrer une chaîne unicode codée json via wp_update_post , ce qui suit a fonctionné pour moi. Trouvé dans 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 ) ); 

Voici un exemple:

$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
la source
-1

Vous pouvez utiliser la fonction WordPress stripslashes_deep ().

<?php stripslashes_deep($your_json);?>

Pour référence, visitez ici

Irfan Bin Hakim
la source
BARBJANE'sest toujours envoyé depuis WordPress comme BARBJANE\'ssi je manque quelque chose ici ...
Si8