Chris Schmitz Chris Schmitz - 4 months ago 44
JSON Question

Converting an array of arrays from Laravel's collection into an object with an array in json

I am generating an an array of categories and subcategories in my Laravel API for use in my client side app.

I'm doing this by using the collection's

filter
and
map
methods to organize the data pulled from the database:

// get the data from the category table
$categoryData = $categories->all()->categories();

// filter the data by category names we know we want and create the multi-dimensional array of the fields we need
$categoryList = $categoryData->filter(function ($value) {
return $value['Category'] == "by Area of Interest" || $value['Category'] == "by Grade Level";
})
->map(function ($value) {
return ['category' => $value['Category'], 'subCategory' => $value['Subcategory']];
});

dd($categoryList);


When I review the die and dump result, I get my collection with it's array of correctly formatted items:

dd result

And if I output it as an array with:

dd($categoryList->toArray());


I see the multi-dimensional array I would expect.

dd result when outputting as an array

The problem I'm running into is when I try to output it as json for my client app to consume.

dd($categoryList->toJson());

If I output as json I get an object that contains the php array indexes as properties and the php sub arrays as objects assigned to those properties.

dd result when outputting to json

What I want is a json object that contains an array of objects. e.g.

$categoryList = [['category' => 'test', 'subCategory' => 'test'], ['category' => 'test', 'subCategory' => 'test']];
dd(json_encode($categoryList));


Which outputs:

example of what I want

Is there something I'm doing wrong with my collection calls?

Update



Per Hognbin's comment:

The call to
$categories->all()->categories();
returns a collection of category data that I then manipulate to get my list.

$categoryData = $categories->all()->categories();
dd($categoryData);


yields:

result of categories->all()

Answer

The problem is that the indexes are the ids of categories which You'll get from eloquent collection when You try to make array from it.

If you want to have a clean array of objects, I suggest doing this:

json_encode(array_values($categoryList->toArray()));

Final implementation by Chris

The above explanation and function calls got me the end result I needed. After confirming it worked via these function calls I looked at the Collection class methods to see how I could implement it using the class. Here's what I did:

$categoryList = $categoryData->filter(function ($value) {
    return $value['Category'] == "by Area of Interest" || $value['Category'] == "by Grade Level";
})
->map(function ($value) {
    return ['category' => $value['Category'], 'subCategory' => $value['Subcategory']];
})
->values()
;

If you look at the Collection class' values() method, it's doing the same thing:

values method in Collection class

Since the Laravel Collection items are stored as an array, the toArray() method call is not needed.