As I write in depth in my 2018 rant My love-hate relationship with PHP Arrays, PHP has a weird way of dealing with arrays, especially when considering interoperability with JSON.

We had an issue in a project where the API (written in PHP) returned inconsistent types for responses with values and ones without when using json_encode.

For example, a successful return value for book might be:

{
	"book": {
		"author": "Jane Doe",
		"publishYear": 2023
	}
}

while an empty result would come out as

{
	"book": []
}

This was caused by how PHP treats sequential arrays and associative arrays:

in PHP, [] is an empty array. A [1, 2, 3] is an array that gets translated to [1, 2, 3] when encoded with json_encode(). A [1 => 'foo', 2 => 'bar'] is an associative array that gets turn into a JSON object: {1: "foo", 2: "bar"}.

The issue comes when the array is empty. An empty array has no keys so it’s always a sequantial array in PHP and is encoded as [] for JSON.

JSON_FORCE_OBJECT flag allows forcing arrays into objects but it turns everything into an object. [] becomes {} but also [1,2] becomes {0: 1, 1: 2} which is not desired.

To force an empty array into an object, you can cast it with (object)$array.

$book = []
if(empty($book)) {
  $book = (object)$book;
}
 
echo json_encode($book);
// {}