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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: jon dot ronnenberg at gmail dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2024 The PHP Group
All rights reserved.
Last updated: Mon Dec 09 07:01:27 2024 UTC