1

I am making a mobile app with Phonegap and using Wordpress as a backend. I am using Advanced Custom Fields with a Google Maps post field which returns a PHP object to the app using JSON API. My Wordpress backend sends a normal JSON object to the app, but inside that object is where a stringified PHP object is returned.

I need to convert the PHP object to a JSON object somehow on the client side(the app which is not in Wordpress). I have looked at other answers that say to use json_encode for this but my problem is that the app is just HTML/Javascript and no PHP. Is there a way to use PHP code in the middle of a Javascript function to do this? Or would it be better to change the backend so that it returns a JSON object instead of a PHP object in the first place? If so, how do I do that?

My experience in PHP is still somewhat limited so any help is appreciated.

edit: To clarify a bit more, I am using Wordpress on a separate domain from my Phonegap app and only using the JSON API plugin on the Wordpress end. I am then using jQuery Ajax calls to retrieve data from the Wordpress backend.

Also the returned PHP object looks like this: a:3:{s:7:\"address\";s:48:\"8915 W 159th St, Orland Hills, IL, United States\";s:3:\"lat\";s:17:\"41.60111599999999\";s:3:\"lng\";s:11:\"-87.8364575\";}

Another way I just thought of as well, would it be possible to just leave it as a PHP object and still read out the values from it somehow? I don't NEED it to be a JSON array, I just need a way to read the individual elements in the array in one way or another.

Here is also a tiny snippet of the JSON returned to clarify what I'm talking about.

"custom_fields": { "location": [ "a:3:{s:7:\"address\";s:48:\"8915 W 159th St, Orland Hills, IL, United States\";s:3:\"lat\";s:17:\"41.60111599999999\";s:3:\"lng\";s:11:\"-87.8364575\";}" ] }

That of course isn't the entire JSON object but it gives you an idea of what I'm dealing with.

chrispytoes
  • 1,714
  • 1
  • 20
  • 53
  • 1
    I've done this plenty of times, but sadly not with the JSON API plugin, so I can't help in your particular case. But judging by the PHP content you're showing, though, it needs to be [unserialized](http://php.net/manual/en/function.unserialize.php) before you pass it to your plugin. What you're showing is a string, not a PHP object. – Hobo Mar 06 '16 at 23:18
  • @Hobo Yes, sorry I will edit the post to clarify that, it is a strigified PHP object. Bascially what happens is the JSON API plugin returns a regular JSON object with all posts in it, but inside that object in the property that contains information about the map is returned in PHP form for some reason. – chrispytoes Mar 06 '16 at 23:23
  • Ok, understood. So ACF doesn't have a setting to unserialize the data? I still think it would be much better to unserialize on the server than to try doing it on the client. Does ACF have a filter on that field that you can hook into? If not, can you just unserialize the field once you have the object (eg `$obj->map_data = unserialize($obj->map_data)`? Apologies if the syntax is off, I haven't coded in PHP for a while – Hobo Mar 06 '16 at 23:34
  • @Hobo I don't believe ACF has a built-in way to return a normal JSON object as I don't think it was made to be used for this. I had to add some extra PHP code I found online to get JSON API to return the ACF fields. I will try poking around now to see if I can find where that property is returned and try to do what you said. – chrispytoes Mar 06 '16 at 23:43
  • Ok that makes more sense. That's a PHP object in a json array, see http://stackoverflow.com/a/29519646/1876047 The problem si that it's been escaped. So, you first want to extract the object from the location list, which you can do by decoding the json structure. After that you want to strip the slashes, I believe PHP has a strip_slashes method? Once that is done you should be able to use the unserialize() method and recover the PHP object. Then, to pass it to your client app, just re-encode it as a JSON using json_encode. Hope this makes sense :) – MrD Mar 06 '16 at 23:43
  • [This thread](https://wordpress.org/support/topic/unserialize-php-arrays-before-building-the-json-response) seems to cover what you're trying to do. I'd start with the last suggestion ("Easy fix without hacking plugin code") to avoid having to change the JSON API plugin (which would cause problems when upgrading). – Hobo Mar 06 '16 at 23:50
  • @Hobo Yes, that seems to be exactly what I'm looking for, unfortunately I'm not very good with PHP yet so I'm not so sure where to put that in my theme, I'm trying to figure it out myself but if you can point me in the right direction that would be much appreciated. – chrispytoes Mar 07 '16 at 00:09
  • You should just be able to copy that code into your theme's `functions.php`. Just don't forget the `new unserialize_php_arrays_before_sending_json()` call underneath it, which does the work of activating it. – Hobo Mar 07 '16 at 00:31
  • @Hobo I added the first part to my functions.php, and the `new unserialize_php_arrays_before_sending_json();` right under it but it doesn't seem to be working. Sorry if I'm messing up something super basic haha. – chrispytoes Mar 07 '16 at 00:42
  • Hmm; no, that sounds right. The poster did say it was untested; wonder if they got something wrong, or if something has changed since he wrote it (as I say, I don't know the JSON API plugin). Just as a test (as I said, it'd break your ability to upgrade), does changing the plugin as outlined in the first post on that thread work? – Hobo Mar 07 '16 at 00:47
  • @Hobo No, that doesn't seem to do anything either. The post was made a year ago and the OP says to add it on line 271, which has probably moved since then so I don't know where to actually put it. However, purpleninja in the comments of the first answer here did give me a temporary solution to use a Javascript function which works perfectly for this, but I know it's best practice to have it return normal JSON so I still want to get that to work but for now I'm just going to use that. – chrispytoes Mar 07 '16 at 01:01

3 Answers3

1

If you're using a JSON API to retrieve the data, then why don't you deliver the data in JSON format to your app? Otherwise you seem to remove much of the point of using an API in the first place... You could of course parse that string in JavaScript if you really want to but that's a very ugly and error prone solution.

The JSON API plugin does seem to use JSON:

https://wordpress.org/plugins/json-api/screenshots/

purpleninja
  • 376
  • 3
  • 11
  • Yeah I know that would be a better solution but like I said, I don't know much PHP so I'm not really sure where to even do that, I didn't write the API myself, I'm using a plugin. Could you point me in the right direction? And yes, the JSON API plugin does return full JSON but inside that JSON object is where the stringified PHP object is, and that is how I am getting that object. – chrispytoes Mar 06 '16 at 23:16
  • 2
    As previously stated you have a string and nothing else. It's a serialized array which you need to unescape and then unserialize. Here's a JS function that might work for you: http://phpjs.org/functions/unserialize/ – purpleninja Mar 07 '16 at 00:42
  • Well that works perfectly! I would rather have Wordpress return a normal JSON object instead but until I get that working I will use that. Thanks! – chrispytoes Mar 07 '16 at 00:51
1

I know you have a solution that works on the front end, but I still think it'd be better to fix this on the server.

Based on our conversation in the comments, I've had a closer look the code in the WordPress forum. The problem seems to be that the location field is an array of strings, not just a string. maybe_unserialize (and is_serialized, which it uses) don't handle arrays. Here's the updated code, which you should be able to drop into your theme's functions.php. I did a quick test, and it works for me.

class unserialize_php_arrays_before_sending_json {
    function __construct() {
        add_action( 'json_api_import_wp_post',
            array( $this, 'json_api_import_wp_post' ),
            10,
            2 );
    }

    function json_api_import_wp_post( $JSON_API_Post, $wp_post ) {
        foreach ( $JSON_API_Post->custom_fields as $key => $custom_field ) {
            if (is_array($custom_field)) {
                $unserialized_array = array();
                foreach($custom_field as $field_key => $field_value) {
                    $unserialized_array[$field_key] = maybe_unserialize( $field_value );
                }
                $JSON_API_Post->custom_fields->$key = $unserialized_array;
            }
            else {
                $JSON_API_Post->custom_fields->$key = maybe_unserialize( $custom_field );
            }
        }
    }
}

new unserialize_php_arrays_before_sending_json();
Hobo
  • 7,536
  • 5
  • 40
  • 50
0

I need to convert the PHP object to a JSON object somehow on the client side(the app which is not in Wordpress).

This bit here leaves me confused. You do not have PHP objects on the client-side, PHP is a back-end technology. What is returned to the client is a string which can be HTML, XML, JSON, plaintext on any other form of encoding.

That said, saying you have an object $obj in PHP, you could pass it to your front-end application creating an end-point retrieve_object.php and in there:

echo json_encode($obj);

So long as that is the only thing your are outputting, you lient-side app can make a request (Eg: AJAX) to retrieve_object.php and get the json object.

BUT , and this is important (!) in doing so you serialize object properties. You will lose any PHP object method. If any object property is an object itself (EG: A DB Connection) then this will be lost too.

Hope this helps!

MrD
  • 4,986
  • 11
  • 48
  • 90