Stefan Stefan - 2 months ago 6
JSON Question

Merge JSON array according to key in PHP and extracting recurring keys

I have a JSON array that looks like:

{
"error": false,
"service_prov_services": [
{
"service_measure": "Darmkrebsfrüherkennung (Schnelltest, Koloskopie)",
"service_prov_type": "Doctor",
"service_type": "Früherkennung und Vorsorge",
"service_prov_name": "Dr. Test",
"addr_street": "xxx Street"
},
{
"service_measure": "Gesundheits-Check-up",
"service_prov_type": "Doctor",
"service_type": "Früherkennung und Vorsorge",
"service_prov_name": "Dr. Test",
"addr_street": "xxx Street"
},

{
"service_measure": "Suchtmittelkonsum",
"service_prov_type": "Doctor",
"service_type": "Gesundheitskurse",
"service_prov_name": "Dr. Test",
"addr_street": "xxx Street"
},
{
"service_measure": "Stressbewältigung oder Entspannung",
"service_prov_type": "Doctor",
"service_type": "Gesundheitskurse",
"service_prov_name": "Dr. Test",
"addr_street": "xxx Street"
},
{
"service_measure": "Schutzimpfung",
"service_prov_type": "Doctor",
"service_type": "Sport und Gesundheit",
"service_prov_name": "Dr. Test",
"addr_street": "xxx Street"
}
]
}


I would like it to be a json array in the following format.
The recurring key values should be extracted and should only be sent once.

{
"error": false,
"service_prov_type": "Doctor",
"service_prov_name": "Dr. Test",
"addr_street": "xxx Street",
"service_prov_services": [
{
"service_type": "Früherkennung und Vorsorge",
"service_measure": "Darmkrebsfrüherkennung
(Schnelltest, Koloskopie)","Gesundheits-
Check-up"
},
{
"service_type": "Gesundheitskurse",
"service_measure": "Suchtmittelkonsum",
"Stressbewältigung oder Entspannung"
},
{
"service_type": "Sport und Gesundheit",
"service_measure": "Schutzimpfung",
}
]
}


Could anyone point out how to do this?
I am able to sort the array with usort, but I cannot seem to extract recurring keys.

Answer

You can follow this road:

  1. convert the json to PHP array using json_decode
  2. iterate through key $service_prov_services. In the course:
    a)store the service_type in an array. On each iteration check if the item belongs to this value, then push to this collection
    b)if not then create new collection and push in that.
    1. At the end of loop you will have collections of service_type
    2. Use this collection in service_prov_services
    3. convert the array back to json using json_encode

UPDATE

Your resultant JSON has service_measure as string and not array. My code gives that as array. I have followed exactly the same steps, except for storing the UTF8 keys in a mapper.

<?php

ini_set('display_errors', 'On');
error_reporting(E_ALL);

$json = <<<EOF
{
    "error": false,
    "service_prov_services": [
        {
            "service_measure": "Darmkrebsfr?herkennung (Schnelltest, Koloskopie)",
            "service_prov_type": "Doctor",
            "service_type": "Fr?herkennung und Vorsorge",
            "service_prov_name": "Dr. Test",
            "addr_street": "xxx Street"
        },
        {
            "service_measure": "Gesundheits-Check-up",
            "service_prov_type": "Doctor",
            "service_type": "Fr?herkennung und Vorsorge",
            "service_prov_name": "Dr. Test",
            "addr_street": "xxx Street"
        },
        {
            "service_measure": "Suchtmittelkonsum",
            "service_prov_type": "Doctor",
            "service_type": "Gesundheitskurse",
            "service_prov_name": "Dr. Test",
            "addr_street": "xxx Street"
        },
        {
            "service_measure": "Stressbew?ltigung oder Entspannung",
            "service_prov_type": "Doctor",
            "service_type": "Gesundheitskurse",
            "service_prov_name": "Dr. Test",
            "addr_street": "xxx Street"
        },
        {
            "service_measure": "Schutzimpfung",
            "service_prov_type": "Doctor",
            "service_type": "Sport und Gesundheit",
            "service_prov_name": "Dr. Test",
            "addr_street": "xxx Street"
        }
    ]
}
EOF;

$listArr = json_decode($json, TRUE);

$service_type = array();
$service_prov_services = array();

$mapper = array();
$entry_list = array();
$mapIndex = 0;  //initialize map index at zero


foreach($listArr['service_prov_services'] as $collection){

    if(in_array($collection['service_type'], array_values($mapper))){
            //make edit to existing entry by pusing service_measure

            //extract the index from mapper now
            foreach($mapper as $key=>$value){
                if($value == $collection['service_type']){
                    $needle = $key;
                    break;
                }
            }

            $arr_service_measure_old = (array)$entry_list[$needle]['service_measure'];
            $arr_service_measure_old[] = $collection['service_measure'];

            //update the array
            $entry_list[$needle] = array(
                'service_type'      =>  $collection['service_type'],
                'service_measure'   =>  $arr_service_measure_old,
            );

    }else{
            //new entry needs to be made
            $currentMapIndex = $mapIndex;
            $mapper[$mapIndex++] = $collection['service_type'];

            $entry_list[$currentMapIndex] = array(
                'service_type'      =>  $collection['service_type'],
                'service_measure'   =>  $collection['service_measure'],
            );

    }

}

echo json_encode($entry_list);

The resultant JSON is :

[
    {
        "service_type": "Fr?herkennung und Vorsorge",
        "service_measure": [
            "Darmkrebsfr?herkennung (Schnelltest, Koloskopie)",
            "Gesundheits-Check-up"
        ]
    },
    {
        "service_type": "Gesundheitskurse",
        "service_measure": [
            "Suchtmittelkonsum",
            "Stressbew?ltigung oder Entspannung"
        ]
    },
    {
        "service_type": "Sport und Gesundheit",
        "service_measure": "Schutzimpfung"
    }
]
Comments