O WordPress está retirando barras invertidas de escape das strings JSON no post_meta

11

Eu pensei que estava facilitando minha vida e tendo consciência do futuro, salvando algum conteúdo como bits de JSON nos campos personalizados post_meta. Infelizmente, o WordPress não concorda e está tornando minha vida incrivelmente difícil.

Eu tenho uma string JSON que se parece essencialmente com isso. Isso é apenas um pouco, e a sequência de comentários é apenas algumas entidades unicode fictícias. A coisa toda é gerada com 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"
    }
}

Infelizmente, depois que eu o salvo update_post_meta, ele sai assim:

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

E com as barras cortadas, não é possível json_decodevoltar ao conteúdo útil.

Alguma idéia de por que o WordPress pode estar fazendo isso, e se existe uma maneira de evitá-lo? Não posso usar o sinalizador JSON_UNESCAPED_UNICODE porque esta é uma instalação do PHP 5.3.x e já tentei codificar htmlentitiesantes da passagem do conteúdo json_encode, mas que captura apenas um pequeno subconjunto de entidades UTF-8.

Desde já, obrigado!

(EDIT: FWIW, eu sei que eu poderia salvar uma matriz diretamente no post_meta e seria serializada e a mágica aconteceria, mas eu apenas gosto da ideia de ter os dados armazenados como JSON. Se não houver uma solução fácil e elegante vou caverna, mas eu estou muito esperando lá é uma solução fácil, elegante!)

Chris Van Patten
fonte

Respostas:

8

Parece que não há como evitá-lo.

A função update_metadata (), responsável por salvar a meta, executa explicitamente um stripslashes_deep () no valor da meta. Essa função removerá barras dos elementos da matriz, se o valor for uma matriz.

Existe um filtro que é executado APÓS chamado sanitize_meta, no qual você pode conectar. Mas, nesse ponto, suas barras já foram removidas, portanto, você não pode determinar com segurança onde elas precisam ser adicionadas novamente (ou pelo menos, não sei como saber a diferença entre citar delimitadores JSON legítimos x bits de valores).

Não posso falar sobre o porquê de fazer isso, mas faz. Provavelmente porque acabou rodando o wpdb-> update, que precisa das seqüências de caracteres sem escape.

Como você temia, provavelmente é melhor apenas armazenar o valor como uma matriz, que será serializada (como você disse). Se você desejar JSON posteriormente, basta executá-lo através de json_encode ().

MathSmath
fonte
Eu tinha medo disso, mas é bom saber por que está acontecendo. Muito obrigado pela resposta rápida!
Chris Van Patten
Este é nem verdadeira, consulte outras respostas :)
jave.web
@ jave.web É verdade que você não pode evitar que update_metadata () execute barras em sua string. As outras respostas fornecem soluções (muito inteligentes) para essencialmente "escapar duas vezes" sua string, para que a remoção inevitável remova essas barras extras, mas mantenha intactas as barras originais. Pessoalmente, ainda diria que a maneira "elegante" de lidar com isso é apenas armazenar dados em uma matriz, o que não requer tratamento especial ou pré-formatação. Em seguida, converta-o para json, se e quando for necessário. Mas essa é apenas a minha preferência.
MathSmath
25

Existe uma maneira elegante de lidar com isso!

Passe a string codificada em JSON wp_slash(). Essa função escapará da barra inicial de cada caractere unicode codificado, o que impedirá sua update_metadata()remoção.

jkereako
fonte
Esta é uma solução alternativa para um bug sério do Wordpress. Muito obrigado!
netAction
2
Essa deve ser a resposta aceita. Eu tive problemas com o conteúdo sendo importado do GitHub por meio do wp_insert_post, onde esse era um problema importante na remoção de barras de amostras de código. Executar a sequência através do wp_slash antes de enviá-lo através do wp_insert_post fez o truque. Obrigado!
Matt Chaves
Isso ainda está sendo útil ainda hoje, perdi horas e horas para encontrar uma solução alternativa para isso sem uma única pista até encontrar isso. Se você quiser adicionar esta resposta à minha pergunta aqui: stackoverflow.com/questions/61091853/… Marcarei como a resposta correta. Muito obrigado!
Jaypee
4

Você pode trapacear no wordpress com algo assim:

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

Esta é a solução fácil * elegante * ...

drmartin
fonte
+1 Isso fez o truque para a minha situação. era um pouco diferente do OP, mas semelhante.
Adam Spriggs
2

Esta função faz a transformação 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 sequência "uXXXX" (X = 0..F, hexadecimal), ela adiciona barra invertida. Antes de enviar para o DB, chame esta função.

Florin Chis
fonte
1

Uma maneira interessante de contornar isso é codificar para base64, veja o exemplo abaixo.

$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
fonte
1

Para quem ainda está lutando para salvar uma string unicode codificada por json via wp_update_post , o seguinte funcionou para mim. Encontrado em 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 ) ); 

Aqui está um exemplo:

$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
fonte
-1

Você pode usar a função stripslashes_deep () do WordPress.

<?php stripslashes_deep($your_json);?>

Para referência visite aqui

Irfan Bin Hakim
fonte
BARBJANE'sainda é enviada a partir do WordPress como BARBJANE\'sa menos que eu estou faltando alguma coisa aqui ...
Si8