WordPress удаляет обратную косую черту из строк JSON в post_meta

11

Я думал, что облегчаю свою жизнь и ориентируюсь в будущее, сохраняя некоторый контент в виде битов JSON в пользовательских полях post_meta. К сожалению, WordPress не согласен и делает мою жизнь невероятно сложной.

У меня есть строка JSON, которая выглядит по существу так. Это всего лишь один бит, а строка комментария - это просто фиктивные юникодные объекты. Все это создается с помощью 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 может делать это, и есть ли способ избежать этого? Я не могу использовать флаг JSON_UNESCAPED_UNICODE, потому что это установка PHP 5.3.x, и я уже пробовал кодировать с помощью htmlentitiesдо передачи содержимого json_encode, но это захватывает только небольшое подмножество объектов UTF-8.

Заранее спасибо!

(РЕДАКТИРОВАТЬ: FWIW, я знаю, что я мог бы просто сохранить массив непосредственно в post_meta, и он был бы сериализован, и волшебство произошло бы, но мне просто нравится идея хранить данные в виде JSON. Если нет простого, элегантного решения Я буду пещерой, но я очень надеюсь , есть это простое, элегантное решение!)

Крис Ван Паттен
источник

Ответы:

8

Не похоже, что есть способ избежать этого.

Функция update_metadata (), которая в конечном итоге отвечает за сохранение мета, явно запускает stripslashes_deep () для значения мета. Эта функция даже удалит косые черты из элементов массива, если значение было массивом.

Есть фильтр, который запускается ПОСЛЕ того, что называется sanitize_meta, к которому вы можете подключиться. Но на этом этапе ваши слэши уже удалены, поэтому вы не можете надежно определить, куда их нужно добавить обратно (или, по крайней мере, я не знаю, как вы могли бы определить разницу между цитированием допустимых разделителей JSON и битов). ценностей).

Не могу сказать, почему он это делает, но это так. Вероятно, потому, что он в конечном итоге запускается через wpdb-> update, для которого нужны неэкранированные строки.

Как вы и опасались, вам, вероятно, лучше просто хранить значение в виде массива, который будет сериализован (как вы сказали). Если вы хотите использовать его как JSON позже, вы можете просто запустить его через json_encode ().

MathSmath
источник
Я боялся этого, но приятно знать, почему это происходит. Большое спасибо за быстрый ответ!
Крис Ван Паттен
Это не так, см. Другие ответы :)
jave.web
@ jave.web Это правда, что вы не можете избежать, чтобы update_metadata () запускала косые черты в вашей строке. Другие ответы предоставляют (очень умные) обходные пути для «двойного выхода» из вашей строки, так что неизбежное удаление удаляет эти дополнительные косые черты, но оставляет исходные косые черты нетронутыми. Я бы лично сказал, что «элегантный» способ справиться с этим - просто хранить данные в массиве, который не требует специальной обработки или предварительного форматирования. Затем преобразовать его в JSON, если и когда вам нужно. Но это только мои предпочтения.
MathSmath
25

Существует элегантный способ справиться с этим!

Передайте строку в кодировке JSON wp_slash(). Эта функция будет экранировать начальную косую черту каждого закодированного символа юникода, что предотвратит update_metadata()их удаление.

jkereako
источник
Это обходной путь для серьезной ошибки Wordpress. Большое спасибо!
netAction
2
Это должен быть принятый ответ. У меня были проблемы с контентом, импортируемым из GitHub через wp_insert_post, где это было основной проблемой, удаляющей косые черты из примеров кода. Выполнение строки через wp_slash перед отправкой через wp_insert_post сделало свое дело. Спасибо!
Мэтт Киз
Это все еще полезно даже сегодня, я потерял часы и часы, чтобы найти обходной путь для этого без единой подсказки, пока я не нашел это. Если вы хотите добавить этот ответ на мой вопрос здесь: stackoverflow.com/questions/61091853/… Я отмечу его как правильный ответ. Спасибо огромное!
Jaypee
4

Вы можете обмануть WordPress с чем-то вроде этого:

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

Это является , что легко * элегантным решением * ...

drmartin
источник
+1 Это помогло моей ситуации. это было немного отличается от ОП, но похоже.
Адам Сприггс
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, шестнадцатеричный) он добавляет обратную косую черту. Перед отправкой в ​​БД, вызовите эту функцию.

Флорин Чис
источник
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

Для тех, кто все еще борется с сохранением строки юникода в кодировке json через wp_update_post , у меня сработало следующее. Найдено в классе-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 ) ); 

Вот пример:

$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
источник
-1

Вы можете использовать функцию WordPress stripslashes_deep ().

<?php stripslashes_deep($your_json);?>

Для ознакомления посетите здесь

Ирфан бен Хаким
источник
BARBJANE'sпо-прежнему отправляется из WordPress, как BARBJANE\'sесли бы я что-то здесь
упустил