WordPressはpost_metaのJSON文字列からエスケープバックスラッシュを削除しています


11

一部のコンテンツをJSONのビットとしてカスタムpost_metaフィールドに保存することで、自分の人生を簡単にし、将来を意識するようになったと思いました。残念ながら、WordPressはこれに同意せず、私の人生を信じられないほど難しくしています。

基本的にこのようなJSON文字列があります。これはほんの1ビットであり、コメント文字列は単なるダミーのUnicodeエンティティです。全体は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"
    }
}

残念ながら、で保存した後update_post_meta、次のように表示されます。

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

そしてスラッシュが取り除かれると、それはできません json_decode有用なコンテンツに戻す。

WordPressがこれを行う理由、およびそれを回避する方法がある場合 これはPHP 5.3.xのインストールなので、JSON_UNESCAPED_UNICODEフラグを使用できません。htmlentitiesコンテンツが渡される前に、json_encode、これはUTF-8エンティティの小さなサブセットしかキャプチャしません。

前もって感謝します!

(編集:FWIW、配列をpost_metaに直接保存するだけでシリアル化されてマジックが発生することはわかっていますが、データをJSONとして保存するというアイデアが気に入っています。簡単でエレガントなソリューションがない場合洞窟探検します、簡単でエレガントな解決策あることを期待しています!)

回答:


8

それを回避する方法はないようです。

最終的にメタの保存を担当するupdate_metadata()関数は、メタ値に対してstripslashes_deep()を明示的に実行します。この関数は、値が配列の場合、配列要素からスラッシュを取り除きます。

sanitize_metaと呼ばれるAFTERの後に実行されるフィルターがあり、これをフックすることができます。しかし、その時点では、スラッシュは既に取り除かれているため、どこに追加する必要があるかを確実に判断することはできません(または、少なくとも、正当なJSON区切り文字とビットの引用の違いをどのように判断するかはわかりません)値の)。

なぜこれを行うのかは言えませんが、そうです。おそらくそれは最終的にwpdb-> updateを介して実行されるため、エスケープされていない文字列が必要です。

あなたが恐れていたように、(あなたが言ったように)シリアライズされる配列として値を格納するだけの方が良いでしょう。後でJSONとして使用する場合は、json_encode()を使用して実行できます。


私はそれを恐れていましたが、なぜそれが起こっているのかを知るのは良いことです。迅速な対応ありがとうございました!
Chris Van Patten

これは真実ではありません。他の回答を参照してください:)
jave.web

@ jave.web確かに、文字列に対してupdate_metadata()がスラッシュを削除するのを避けることはできません。他の回答は、文字列を本質的に「ダブルエスケープ」する(非常にスマートな)回避策を提供します。そのため、不可避のストリッピングによって余分なスラッシュは削除されますが、元のスラッシュはそのまま残ります。これを処理する「エレガントな」方法は、配列にデータを格納することであり、特別な処理や事前フォーマットは必要ありません。次に、必要に応じてjsonに変換します。しかし、それは私の好みです。
MathSmath

25

これを処理するエレガントな方法があります!

JSONエンコードされた文字列をを介して渡しますwp_slash()。その関数は、エンコードされた各Unicode文字の先頭のスラッシュをエスケープし、それらが取り除かれることを防ぎupdate_metadata()ます。


これは深刻なWordpressバグの回避策です。どうもありがとう!
netAction

2
これは受け入れられる答えになるはずです。コンテンツがwp_insert_postを介してGitHubからインポートされるという問題がありました。これは、コードサンプルからスラッシュを削除する大きな問題でした。wp_insert_postで送信する前にwp_slashで文字列を実行するとうまくいきました。ありがとう!
マット・キーズ

これは今日でも役に立ちます。これを見つけるまで、手掛かりが1つもないため、この回避策を見つけるのに何時間も費やしました。ここで私の質問にこの応答を追加する場合:stackoverflow.com/questions/61091853/…正解としてマークします。どうもありがとうございます!
ジェイピー

4

あなたはこのようなものでワードプレスをだますことができます:

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

これがあることは容易 * エレガントなソリューション ... *


+1これは私の状況にトリックをもたらしました。OPとは少し異なりますが、似ています。
アダムSpriggs

2

この関数は、preg_replaceを使用して変換を行います。

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

各 "uXXXX"(X = 0..F、16進数)シーケンスの前に、バックスラッシュを追加します。DBに送信する前に、この関数を呼び出します。


1

これを回避する興味深い方法は、以下の例を参照してbase64にエンコードすることです。

$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 ))

1

jpでエンコードされたUnicode文字列をwp_update_postを介して保存することにまだ苦労している人にとっては、以下がうまくいきました。で発見されたクラス-WP-残り-投稿-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 ) ); 

次に例を示します。

$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 ) );

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.