not sure what I'm doing wrong here but i have my Json string and I'm trying to get the values to print out in the IF statement
i.e:
63,52,55
here is my code:
$jayjay = '{"items":{"cID":"63","qty":"2"},"items":{"cID":"52","qty":"1"},"items":{"cID":"55","qty":"1"}}';
echo $jayjay;
$obj = json_decode($jayjay, TRUE);
for($i=0; $i<=count($obj['items']); $i++) {
echo $obj['items'][$i]['cID'];
echo ",";
}
but the output is just blank and i cant figure out why
Any help would be appreciated.
Thank you
The problem is that you have key "items" multiple time in your JSON which is wrong. Please note that JSON key must be unique for well formed JSON.
Basically there is no error if you use more than one key with the same name, but in JSON, the last key with the same name is the one that is gonna be used. In your case, the key "items" would be better to contain an array of objects as it's value:
{'items' : [{"cID":"63","qty":"2"}, {"cID":"52","qty":"1"}, {"..." : "..."}]}
As Hamish stated in his comment, you can't have json as you've supplied. The keys (which is items in this case) are going to overwrite each other until the last key.
What I suggest is if you create an array like this:
{"items":[{"cID":"63","qty":"2"}, {"cID":"52","qty":"1"},.....]}
Allowing you to itterate as you require.
Meaning you can simply loop as you require:
$items = json_decode($json, true);
foreach($items as $thing){
echo $thing['cID'];
echo ",";
}
As has already been pointed out, your JSON data is malformed.
But since Stack Overflow is a rather inefficient method of syntax checking your data, I would suggest using a JSON linter (such as this one) on static JSON data in the future. Or at the very least, checking the return value of json_last_error after parsing to look for potential problems at least when testing or debugging.
Related
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.
I have problem with a json, this json keeps updating, so the last entry will never be the same. This is the json:
{"channel":{"id":274304,"name":"Water","description":"Record water consumption.","latitude":"0.0","longitude":"0.0","field1":"Water","created_at":"2017-05-17T16:27:46Z","updated_at":"2017-05-19T01:01:07Z","last_entry_id":28},"feeds":[{"created_at":"2017-05-19T00:51:35Z","entry_id":1,"field1":"288"},{"created_at":"2017-05-19T00:51:50Z","entry_id":2,"field1":"304"}]}
I have something like this in my php code, where the variable $cool contains the decoded json.
$x= $cool->feeds[2]->field1;
But when the json updates, feeds[2] will not be the last entry. So i was thinking of using arrays to store all data. But i don't know how to do this. Can you help me?
If $cool->feeds is an array as I assume, you can use end to get its last item:
$x = end($cool->feeds)->field1;
If you want to get the last element, you also can use array_pop()
$x = array_pop($cool->feeds)->field1;
I have an array of 'servers' that I'm storing in a JSON file.
The JSON file looks like this:
{"1":{"available":1,"players":0,"maxplayers":4}}
I retrieve this value with this:
$servers = (array) json_decode(file_get_contents("activeservers.json"));
However, when I try to access the array with $server = $servers[$id], $server is null. I noticed that the key is in quotes, so I also tried casting $id to a string, and surrounding it with quotes (") which didn't work.
Something to note, is that this code is returning "NULL":
foreach(array_keys($servers) as $key){
var_dump($servers[$key]);
}
Your code is wrong. Also you don't need to type cast when doing a json_decode, you can instead set the second parameter to true more info here.
Also you don't need to use the array_keys function in your foreach loop,
try this.
$json = '{"1":{"available":1,"players":0,"maxplayers":4}}';
$servers = json_decode($json, true);
foreach($servers as $key => $value) {
print $value["available"];
}
Do a print_r($value) to get all the array keys available to use. Also you could take advantage of the $key variable to print out the array key of the parent array.
Thanks, #Rizier123 (who solved the question).
Apparently passing TRUE as the second parameter to my json_decode function fixes the issue.
After checking the PHP documentation for json_decode() (PHP: json_decode), it seems that passing this parameter means that the resulting decoded array is automatically converted into an associative array (and this is recurring, meaning that this automatically happens for sub-arrays).
Edit: #Rizier123 also says that "you might want to read: stackoverflow.com/a/10333200 to understand a bit better why it is so "weird" and your method didn't work properly."
I've one working REST API developed using Slim PHP framework.
It's working absolutely fine.
The only issue is when there is no error present i.e. an array $errors is empty it comes as an array in JSON response but when the array $errors contains any error like $errors['user_name'] then it comes as an object in JSON response.
Actually I want to return the array when error is present. How should I do this? Can someone please help me in this regard?
Thanks in advance.
When your $errors is not empty, pass it through json_encode and echo it.
It will give you JSON object in return,
then convert JSON object into JavaScript array. (see the following code.)
var o = {"0":"1","1":"2","2":"3","3":"4"}; // your response object here
var arr = Object.keys(o).map(function(k) { return o[k] });
console.log(arr);
Recently got a close issue with Symfony's JsonResponse::create()
Turns out arrays with index not starting at 0 will be encoded into objects, as well as arrays with "holes", and probably any array with at least one non-int key.
In other word, arrays with anything else than consecutive numeric keys starting from index 0 seem to be encoded as object.
I guess this is designed to avoid sending big empty arrays when you map a handful of datas with big indices like [14334, 839493, 246193], and is probably documented somewhere.
Learning if this is a Symfony of json_encode behavior from comments would be welcomed addition :)
Note : Even if you return an array, it seems necessary to wrap it in an object for GET request to prevent some XSSI and JSON-JavaScript Hijacking.
I'm a newbie in the PHP area, so please bear with my question.
Basically I have/will have a pretty big json file, and I need to query the file to get a single entry based on the key provided. An example would be as follow:
{
"key1" : {value1},
"key2" : {value2},
...,
"keyn" : {valuen}
}
I will need to retrieve only one value at any one request, and hope to get a better performance.
The basic way to deal with this sort of handling in PHP from my search is to use json_decode() and then foreach.
However, this approach seems like need to iterate through the whole file based on the order of the key and what the key I am looking for. So if I am looking for keyn, then essentially I have to read from top to bottom of the large file. (Yep, I can use some sort algorithm to get a better result)
But from my understanding, JSON is basically another form of HashMap, so given HashMap can get easily and fast, is there a similar way in PhP to get the best performance out of it?
Well, given the structure you provided you definitely don't need to loop through the entire object.
If you're looking for keyn, you would just do:
$obj = json_decode($input);
echo $obj->keyn;
Maybe I'm missing something obvious. If you want to prevent having to json_decode the entire object, your question makes a bit more sense though... but that's not what you're asking.
From JSON.org
JSON is built on two structures:
A collection of name/value pairs. In various languages, this is realized as an object, >record, struct, dictionary, hash table, keyed list, or associative array.
An ordered list of values. In most languages, this is realized as an array, vector, list, or >sequence.
You can't just interact with json without first using json_decode() to turn it into a usable object. But if you know the keys, after running json_decode() you can interact with it (because it's now an object). for example:
<?php
$string = '{"foo": "bar", "cool": "attr"}';
$result = json_decode($string);
// Result: object(stdClass)#1 (2) { ["foo"]=> string(3) "bar" ["cool"]=> string(4) "attr" }
var_dump($result);
// Prints "bar"
echo $result->foo;
// Prints "attr"
echo $result->cool;
?>
In situations like this, var_dump() and print_r() are your friends.
There really isn't any magical way to find the value without using any kind of loop
I haven't benchmarked this:
This is how I would approach the problem without having to finish the iterating over the whole tree if and when a match is foudn
$key = 'keyn'
$obj = json_decode(file_get_contents('path/to/your/file'), true);
$len = count($obj);
$match = false;
for($ii = 0; $ii < $len; $ii++){
$curr = $obj[$ii];
if($curr == $key) {
$match = $curr;
}
break;
}
In PHP you can use function: file_get_contents to parse JSON file. You have to go through each and every key-value pairs.