logo

json_encode with non-consecutive array keys

Why your JSON arrays become objects after filtering

Joel Clermont
Joel Clermont
2026-02-02

Here's a gotcha that's bitten me more than once.

When you json_encode a PHP array with non-consecutive keys, you get an object instead of an array:

$items = [0 => 'a', 1 => 'b', 2 => 'c'];
json_encode($items);
// ["a","b","c"]

$items = [0 => 'a', 2 => 'c', 5 => 'f'];
json_encode($items);
// {"0":"a","2":"c","5":"f"}

But this also happens when you filter or unset elements from an array without any numeric keys:

$users = ['Alice', 'Bob', 'Charlie'];
unset($users[1]);

json_encode($users);
// {"0":"Alice","2":"Charlie"}  <-- Object, not array!

The fix is simple:

$users = array_values($users);
json_encode($users);
// ["Alice","Charlie"]  <-- Array again

And the same thing applies with Laravel collections too:

$users = collect(['Alice', 'Bob', 'Charlie'])
    ->filter(fn($u) => $u !== 'Bob');

$users->toJson();
// {"0":"Alice","2":"Charlie"}

With a similar fix:

$users = collect(['Alice', 'Bob', 'Charlie'])
    ->filter(fn($u) => $u !== 'Bob')
    ->values();

$users->toJson();
// ["Alice","Charlie"]

This matters a lot when building APIs. If your API schema specifies you always return an array, but then it occasionally sends an object, API consumers could break.

Here to help,

Joel

P.S. API design has lots of little gotchas like this. If your API is behaving strangely, book a Get Unstuck call and we'll figure it out.

Toss a coin in the jar if you found this helpful.
Want a tip like this in your inbox every weekday? Sign up below 👇🏼
email
No spam. Only real-world advice.