Leave a Reply

7 comments

  1. Doesn’t look like there’s any way to avoid it.

    The update_metadata() function, which is ultimately responsible for saving the meta, explicitly runs a stripslashes_deep() on the meta value. This function will even strip slashes from array elements, if the value were an array.

    Theres a filter that’s run AFTER that called sanitize_meta, which you could hook in to. But at that point, your slashes have already been stripped, so you can’t reliably determine where they needed to be added back in (or at least, I don’t know how you would tell the difference between quoting legitimate JSON delimiters vs bits of values).

    Can’t speak to why it does this, but it does. Probably because it’s eventually run through wpdb->update, which needs the strings unescaped.

    As you feared, you’re probably better off just storing the value as an array, which’ll get serialized (as you said). If you want it as JSON later, you can just run it through json_encode().

  2. There is an elegant way to handle this!

    Pass the JSON encoded string through wp_slash(). That function will escape the leading slash of each encoded unicode character, which will prevent update_metadata() from stripping them.

  3. You can cheat to wordpress with something like this:

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

    This is that easy *elegant solution*…

  4. This function does the transformation using preg_replace:

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

    Before each “uXXXX” (X=0..F, hexadecimal) sequence it adds backslash. Before submitting to DB, call this function.

  5. For anyone still struggling with saving a json encoded unicode string via wp_update_post, the following worked for me. Found in 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 ) ); 
    

    Here’s an example:

    $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 ) );
    
  6. An interest way around this is to encode to base64 see example below.

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