php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #74551 json_encode() assumes that one dimensional array is an object
Submitted: 2017-05-06 13:20 UTC Modified: 2017-05-06 13:31 UTC
From: jon dot ronnenberg at gmail dot com Assigned:
Status: Not a bug Package: JSON related
PHP Version: 7.0.18 OS: Linux Ubuntu Mate 16.04
Private report: No CVE-ID: None
 [2017-05-06 13:20 UTC] jon dot ronnenberg at gmail dot com
Description:
------------
<?php
## json_encode() assumes that one dimensional array is an object ##

# Note, To run the entire bug report in php, just copy/paste the entire
# content into a php file and run php your_file.ph

# Unsetting an element will also remove the keys.
# json_encode() will now assume that this is an object,
# and will encode it as such.
# ref: http:#php.net/manual/en/function.json-encode.php#94157

# Note, that JSON_PRETTY_PRINT has no effect on the behavior

# Example:
$array = [0,1,2];
print_r(json_encode($array, JSON_PRETTY_PRINT));
unset($array[1]);
print_r(json_encode($array, JSON_PRETTY_PRINT));

# The real issue and bug introducing confusing comes with array_filter.

# Example:
$array = [0,1,2,3,4,5,6,7,8,9,10];
$odds = function($d) { return $d % 2; };
print_r(json_encode(array_filter($array, $odds), JSON_PRETTY_PRINT));

# The work-around is to always use array_values, when you know that you will
# serialize a one dimensional array.

# Example:
$array = [0,1,2,3,4,5,6,7,8,9,10];
$odds = function($d) { return $d % 2; };
print_r(json_encode(array_values(array_filter($array, $odds)), JSON_PRETTY_PRINT));

# Since the data manipulation is often handled in other layers than the
# serialization, this can lead to subtle and hard to trace bugs.
# Often only found when deployed since this does not happen in all cases,
# as shown below.

# Example:
$array = [0,1,2,3,4,5,6,7,8,9,10];
$below2 = function($d) { return $d < 2; };
print_r(json_encode(array_filter($array, $below2), JSON_PRETTY_PRINT));

# Changing the behavior of array_filter might introduce breaking change
# while changing how json_encode handles one dimensional arrays should
# not.

# I'm not filing this as a bug, since it has been reported seven years
# ago, but it definitely tangents a bug.
# Seven years ago, simoncpu, reported this behavior in the User Contributed Notes,
# http://php.net/manual/en/function.json-encode.php#94157

# Another bug report touches on the subject:
# https://bugs.php.net/bug.php?id=45162
# But it's hard to distill what the author expect or believe to be wrong
# with the behavior.
# This report tries to be concise and has nothing to do with associative arrays.
?>


Test script:
---------------
# The two print_r statements should output the same:
$array = [0,1,2];
print_r(json_encode($array, JSON_PRETTY_PRINT));
unset($array[1]);
print_r(json_encode($array, JSON_PRETTY_PRINT

Expected result:
----------------
[
    0,
    1,
    2
][
    0,
    1,
    2
]

Actual result:
--------------
[
    0,
    1,
    2
]{
    "0": 0,
    "2": 2
}

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-05-06 13:24 UTC] jon dot ronnenberg at gmail dot com
The Test script should have been:
$array = [0,1,2];
print_r(json_encode($array, JSON_PRETTY_PRINT));
unset($array[1]);
print_r(json_encode($array, JSON_PRETTY_PRINT));
 [2017-05-06 13:31 UTC] danack@php.net
-Status: Open +Status: Not a bug
 [2017-05-06 13:31 UTC] danack@php.net
"The two print_r statements should output the same:"

No they shouldn't. 

One is what every language considers an array - zero based index, with contiguous incrementing keys.

The other is what most languages consider a map as it has non-contiguous keys. 

json_encode is correctly converting the array like data to an array, and the map like data to a Javascript map/dict.

Jani already noted this in the 2008 bug report: "Note: array and assoc-array are different things. Latter being "object" in json."

Additionally, please consider writing shorter, clearer bug reports. Putting a description of the expected and actual output first, rather than historical notes would make for a clearer bug report.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Sat Dec 14 08:01:23 2019 UTC