This is my axios request
axios({
method: 'put',
url: url,
data: data
}).then(function (response) {
console.log(response.data)
})
.catch(function (error) {
console.log(error)
})
It's being made from a vue component to submit form data (a table component).
Then I've tried the following JSON objects for data
"building": {
"a": ['Level 1', 0.0, 0, '', '', true],
"b": ['Level 2', 3.8, 40, '', '', false],
"c": ['Level 3', 7.6, 50, '', '', false],
"d": ['Level 4', 11.4, 50, '', '', false]
} // keys not numeric
"building": {
"1": ['Level 1', 0.0, 0, '', '', true],
"2": ['Level 2', 3.8, 40, '', '', false],
"3": ['Level 3', 7.6, 50, '', '', false],
"4": ['Level 4', 11.4, 50, '', '', false]
} // keys don't start at 0
"building": {
"0": ['Level 1', 0.0, 0, '', '', true],
"2": ['Level 2', 3.8, 40, '', '', false],
"3": ['Level 3', 7.6, 50, '', '', false],
"4": ['Level 4', 11.4, 50, '', '', false]
} // keys not consecutive
"building": {
"0": ['Level 1', 0.0, 0, '', '', true],
"1": ['Level 2', 3.8, 40, '', '', false],
"2": ['Level 3', 7.6, 50, '', '', false],
"3": ['Level 4', 11.4, 50, '', '', false]
} // keys are numeric, consecutive, start at 0
The first 3 all remain as objects when I receive them but the 4th (numeric, consecutive, start at 0) gets converted to an array.
How do I stop this from happening?
Clarifications
- I want the data I receive to be an object
- PHP 8 is the backend receiving the put request and then sending the data straight back as the response
- I am doing
console.log(data)
just before sending the axios request and that's an object for all 4. Then theconsole.log(response.data)
is a object for the first 3 and an array for the last.
CodePudding user response:
Your problem is that PHP does not distinguish arrays and objects. When converting to and from JSON, it uses a rule to determine whether an associative array should convert to a JSON array or a JSON object. If the keys are sequential numeric keys starting at 0, it converts it to a JSON array. Otherwise, it converts it to an object. Whether the keys are strings or numbers is apparently irrelevant.
The solution is to not convert to and from associative arrays, but instead let json_decode()
produce mixes of stdClass
objects and arrays. This allows it to keep track of what is or isn't an object. To do that, either don't pass a second parameter when decoding, or pass an explicit false
:
// this variable will probably be of type stdClass
$decoded = json_decode($input, false);
When processing stdClass
objects in PHP, you have to be a little more verbose. You'll use methods like property_exists()
(instead of array_key_exists()
or isset()
) and to iterate, you'll need to cast to an array
first, for example:
foreach ((array)$decoded as $key => $value) {
}
If you don't have control over the JSON decoding ont he server, you might want to consider changing your data model so that it doesn't have numeric keys, or write code on the client side that can handle arrays sometimes appearing in the JSON when objects are expected. It's annoying, but that's a decision PHP made a long time ago and we just have to deal with it.