Yes, I have read previous questions and I know how to access a JSON object and how to convert it into an array. I know about json_encode/decode. My problem is that my JSON response has a string, arrays and all and it will always return NULL when I access the data directly.
object(Unirest\Response)#8 (4) {
["code"]=>
int(200)
["body"]=>
string(666) "{ "ticker": "AAPL:US", ".."
["headers"]=>
array(9) {
[0]=>
string(15) "HTTP/1.1 200 OK"
Normally you would be able to directly access the object like this and this worked just fine when I last accessed the script a few days ago:
$response->body->ticker
Or you could use json_decode with true to turn it into an array.
$array = json_decode($response->body, true);
However, all of this no longer works. I believe they changed something with the output because it was working just a while ago but I have no clue. Any idea how to access the ticker data? I tested it with a different API and the same commands are working just fine to retrieve data from a different API, but the output seems to be different.
$response->body is a json string assuming you didnt shorten it so much as to loose someting important and therefore needs to be seperately converted to a PHP data item.
As its a json string representing an object why not convert it to a PHP object like so
$body = json_decode($response->body);
Then you can address its properties like
$body->ticker
Alternatively
$response->body = json_decode($response->body);
Now you can address it as you expected i.e.
$response->body->ticker
Ok, finally solved it after reading this answer:
PHP json_decode() returns NULL with valid JSON?
Apparently, as I assumed earlier it was a formatting issue. I did not know that JSON would return NULL if the object includes non-UTF8 code and/or BOM codes.
I couldn't find any BOM codes but I suppose there was some non-UTF8 that was breaking it.
Long story short this works:
$dec = json_decode( preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $response->body), true );
echo $dec['ticker'];
Well at least I now know a lot more about JSON which will come in handy some day ;)
Related
I've managed to send some parameters via POST to a .php file. When I invoke var_dump($_POST);, I get the following output:
["{"abc":"1","def":"2"}"]=>
string(0) ""
I've tried to process this many, many times but I can't seem to access the variables inside the String. json_decode doesn't even work on it. What's going on here?
Somehow you have managed to transmit your data with its value as the key and no attached value, so you need to address that in whatever code is accessing the server (Perhaps you used JSON.Stringify on the object instead of just passing the object?). Until you have fixed that, you can access your data like this:
$json = json_decode(array_keys($_POST)[0]);
print_r($json);
Output:
stdClass Object (
[abc] => 1
[def] => 2
)
I'm trying to come up with a simple approach for extracting data from a multitude of json data sources where the reference is stored in a string literal. This is easy to do when the object structure is known but is there any way to get php to interpret the string literal as it would directly in code?
$data = json_decode('
{
"foo": 1,
"object": {
"foo": 1.1,
"bar": 1.2
},
"array": [
"foo",
"bar"
]
}
');
// Explicitly coded reference all work, of course
var_dump($data->foo); // int(1)
var_dump($data->object->foo); // float(1.1)
var_dump($data->array[0]); // string(3) "foo"
And I know that I can access an object's property from a string literal like this:
$string = 'foo';
var_dump($data->$string); // int(1)
var_dump($data->object->$string); // float(1.1)
Is there any way to go about achieving this for the second and third references, without having to break up the string and loop through the object recursively until each element is found?
$string = 'object->foo';
var_dump($data->$string);
$string = 'array[0]';
var_dump($data->$string);
If there is nothing native to PHP for handling this, is there a library or anything that I could use to make this process easier?
Edit: To provide some extra clarity, this is an application where a JSON feed can be configured through the UI and an administrator can extract values from the JSON feed. This works fine for simpler JSON structures but breaks down when they're trying to pull a value such as $foo->bar->baz[0]->qux->corge. I'm trying to find an easier way to get values such as this when the structure changes and I can't account for every possibility within the code.
Since you are using JSON, i‘d use JSON Pointers. Here is their official spec
What they do is providing a query language for json objects (similar to XPath for XML). Accessing your foo within object would result in a query like /object/foo.
Now you‘d have your users specify the json pointer queries, and use a json pointer library to perform the actual queries. This has the advantage that if you ever decide to ditch PHP for say Java, you’d only need to use a JSON Pointer implementation for Java and your users won‘t be impacted by the change.
So... I need to save a large-ish amount of data from a platform with an excruciatingly limited amount of memory.
Because of this, I'm basically storing the data on my webserver, using a php script to just write JSON to a flat file, because I'm lazy af.
I could go to the trouble of having it store the data in my mysql server, but frankly the flat file thing should have been trivial, but I've run up against a problem. There are several quick and dirty workarounds that would fix it, but I've been trying to fix it the "right" way (I know, I know, the right way would be to just store the data in mysql, but I actually need to be able to take the json file this produces and send it back to the platform that needs the data (In a ridiculously roundabout fashion), so it made sense to just have the php save it as a flat file in the first place. And It's already working, aside from this one issue, so I hate to reimpliment.
See... Because of the low memory on the platform I'm sending the json to my server from... I'm sending things one field at a time. Each call to the php script is only setting ONE field.
So basically what I'm doing is loading the file from disk if it exists, and running it through json_decode to get my storage object, and then the php file gets a key argument and a value argument, and if the key is something like "object1,object2", it explodes that, gets the length of the resulting array, and then stores the value in $data->$key[0]->$key[1].
Then it's saved back to disk with fwrite($file, json_encode($data));
This is all working perfectly. Except when $value is a simple string. If it's an array, it works perfectly. If it's a number, it works fine. If it's a string, I get null from json_decode. I have tried every way I can think of to force quotes on to the ends of the $value variable in the hopes of getting json_decode to recognize it. Nothing works.
I've tried setting $data->$key[0]->$key[1] = $value in cases where value is a string, and not an array or number. No dice, php just complains that I'm trying to set an object that doesn't exist. It's fine if I'm using the output of json_decode to set the field, but it simply will not accept a string on its own.
So I have no idea.
Does anyone know how I can either get json_decode to not choke on a string that's just a string, or add a new field to an existing php object without using the output of json_decode?
I'm sure there's something obvious I'm missing. It should be clear I'm no php guru. I've never really used arrays and objects in php, so their vagaries are not something I'm familiar with.
Solutions I'm already aware of, but would prefer to avoid, are: I could have the platform that's sending the post requests wrap single, non-numeric values with square braces, creating a single item array, but this shouldn't be necessary, as far as I'm aware, so doing this bothers me (And ends up costing me something like half a kilobyte of storage that shouldn't need to be used).
I could also change some of my json from objects to arrays in order to get php to let me add items more readily, but it seems like there should be a solution that doesn't require that, so I'd really prefer not to...
I skim through your post.
And I know this works for StdClass :
$yourClass->newField = $string;
Is this what you wanted ?
OK so... ultimately, as succinctly as possible, the problem was this:
Assuming we have this JSON in $data:
{
"key1":
{
"key2":["somedata","someotherdata"]
}
}
And we want it to be:
{
"key1":
{
"key2":["somedata","someotherdata"],
"key3":"key3data"
}
}
The php script has received "key=key1,key3&value=key3data" as its post data, and is initialized thusly:
$key = $_POST["key"];
$key = explode($key,",");
$value = $_POST["value"];
...which provides us with an array ($key) representing the nested json key we want to set as a field, and a variable ($value) holding the value we want to set it to.
Approach #1:
$data->$key[0]->$key[1] = json_decode($value);
...fails. It creates this JSON when we re-encode $data:
{
"key1":
{
"key2":["somedata","someotherdata"],
"key3":null
}
}
Approach #2:
$data->$key[0]->$key[1] = $value;
...also fails. It fails to insert the field into $data at all.
But then I realized... the problem with #2 is that it won't let me set the nonexistent field, and the problem with approach #1 is that it sets the field wrong.
So all I have to do is brute force it thusly:
$data->$key[0]->$key[1] = json_decode($value);
if (json_decode($value) == NULL)
{
$data->$key[0]->$key[1] = $value;
}
This works! Since Approach #1 has created the field (Albeit with the incorrect value), PHP now allows me to set the value of that field without complaint.
It's a very brute force sort of means of fixing the problem, and I'm sure there are better ones, if I understood PHP objects better. But this works, so at least I have my code working.
CONTEXT
I'm using json_decode to convert the contents of an Facebook open graph call into a php object.
EDIT to add code
My code looks like this:
$json = json_decode(file_get_contents("http://graph.facebook.com/http://example.com"),true);
var_dump($json);
A var_dump of the resulting object looks like this:
ARRAY(3) { ["ID"]=> STRING(18) "HTTP://EXAMPLE.COM" ["SHARES"]=> INT(14604317) ["COMMENTS"]=> INT(11300) }
PROBLEM
I would like to get the 12 from this object. I assumed that $json->shares would return 12, but instead it returns null. Any idea what the correct syntax for retrieving the 12 would be?
Your array doesn't look right. Check out http://graph.facebook.com/http://example.com in a browser, notice how the keys and values are all lowercase, not uppercase like you have.
If you really are testing http://graph.facebook.com/http://example.com, then this will just work:
$array = json_decode(file_get_contents('http://graph.facebook.com/http://example.com'), true);
echo $array['shares'];
This gives me 14604317 which I can see in my browser is the correct result.
Note you have an array, not an object. So use array notation:
{"email":"test#example.com","timestamp":1346345321,"newsletter":{"newsletter_user_list_id":"3648511","newsletter_id":"613267","newsletter_send_id":"657025"},"category":["EST_TEST","Newsletter"],"event":"open"}
I'm having trouble parsing this string. It's from Sendgrid's Event API, it seems to be "almost" JSON, but json_decode won't work. My goal is to get the data into an array, then into a MySQL table. I'm not asking anyone to write the code for me, just point me toward the correct method. Do I use the explode function, then json_decode?.
(I'm slowly teaching myself PHP, sorry if the question is not clear)
I think you're not using the json_decode function with $assoc = true, so you're getting an object rather than an array
$json =
'{"email":"test#example.com","timestamp":1346345321,"newsletter":{"newsletter_user_list_id":"3648511","newsletter_id":"613267","newsletter_send_id":"657025"},"category":["EST_TEST","Newsletter"],"event":"open"}';
var_dump(json_decode($json, true));
You'll get the result as array;