Rain Man Rain Man - 1 month ago 10
JSON Question

How to format the JSON output to the desired format

I am trying to create a custom controller for the WordPress JSON API plugin and so far everything is working except the JSON Data I have is not in the correct format.

This is my current JSON output:

{
"status": "ok",
"all_tags": {
"tag-1": {
"term_name": "Tag 1",
"category_details": {
"0": {
"category_ID": 8,
"category_name": "category 1",
"category_count": 2
},
"2": {
"category_ID": 13,
"category_name": "category 2",
"category_count": 1
}
}
},
"tag-2": {
"term_name": "Tag 2",
"category_details": [
{
"category_ID": 8,
"category_name": "category 1",
"category_count": 2
}
]
}
}
}


However, in order to parse the data I must have the json data in a specific format. The correct format should be like this:

{
"status": "ok",
"all_tags": [
{
"id": 1,
"term_name": "Tag 1",
"category_details": [
{
"id": 2,
"category_ID": 8,
"category_name": "category 1",
"category_count": 2
},
{
"id": 3,
"category_ID": 13,
"category_name": "category 2",
"category_count": 1
}
]
},
{
"id": 2,
"term_name": "Tag 2",
"category_details": [
{
"id": 2,
"category_ID": 8,
"category_name": "category 1",
"category_count": 2
}
]
}
]
}


This is how I am creating the array for the json:

<?php
...
$cats_all = array(); // the array
if (!isset($cats_all[$custom_term->slug])) {

// create the array

$cats_all[$custom_term->slug] = array(
'term_name' => $custom_term->name,
'category_details' => array(
array(
'category_ID' => $categories[0]->term_id,
'category_name' => $categories[0]->name,
'category_count' => $mycats[0]->category_count
)
)
);
} else {
$cats_all[$custom_term->slug]['category_details'][] = array(
'category_ID' => $categories[0]->term_id,
'category_name' => $categories[0]->name,
'category_count' => $mycats[0]->category_count
);
}
...
// remove duplicates
$input = $this->super_unique( $cats_all );
// return the array for json output by the plugin
return array(
'all_tags' => $input,
);


Any help will be greatly appreciated. Also the entire controller can be viewed here.

Answer

There are two things you need to achieve:

  1. The all_tags value must be a sequential array, not an associative one. This you can achieve by taking the array_values at the last statement:

    return array(
        'all_tags' => array_values($input)
    );
    
  2. The category_details values must be sequential arrays, not associative ones. This one is more tricky, as you actually do create them as sequential arrays, but the function super_unique will sometimes turn them into associative arrays, when it eliminates at least one duplicate. I suggest this fix to the function super_unique by adding two statements, around this one:

    $result = array_map( 'unserialize', array_unique( array_map( 'serialize', $array ) ) );
    

    To get this:

    $is_seq = end(array_keys($array)) == count($array)-1;
    $result = array_map( 'unserialize', array_unique( array_map( 'serialize', $array ) ) );
    if ($is_seq) $result = array_values($result);
    

    If you get an error on end, then you can use this for that line instead:

    end($array); $is_seq = key($array) == count($array)-1;
    

    The $is_seq variable checks that $array is sequential, and if so, calls array_values after the removal of the duplicates, which always returns a sequential array.

Comments