Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merging two complex objects in PHP

Tags:

json

php

I have two data objects converted from JSON. both are quite deeply complex and I'd like to merge them in a similar fashion to how jQuery would merge two objects using extend.

example

JSON 1:

{
    ...
    "blah":
    {
        "params":
        {
            "foo":
            {
                "default": "bar",
                "misc": "0",
                ...
            },
            ...
        },
        ...
    },
    ...
}

JSON 2:

{
    ...
    "blah":
    {
        "params":
        {
            "foo":
            {
                "value": "val",
                "misc": "1",
                ...
            },
            ...
        },
        ...
    },
    ...
}

Merged into

{
    ...
    "blah":
    {
        "params":
        {
            "foo":
            {
                "default": "bar",
                "value": "val",
                "misc": "1",
                ...
            },
            ...
        },
        ...
    },
    ...
}

What's the best way to approach this with PHP objects.

like image 283
9point6 Avatar asked Feb 11 '12 16:02

9point6


People also ask

How to combine two objects in PHP?

Approach 1: Convert object into data array and merge them using array_merge() function and convert this merged array back into object of class stdClass. Note: While merging the objects using array_merge(), elements of array in argument1 are overwritten by elements of array in argument2.

How to merge multidimensional array in PHP?

The array_merge_recursive() function merges one or more arrays into one array. The difference between this function and the array_merge() function is when two or more array elements have the same key. Instead of override the keys, the array_merge_recursive() function makes the value as an array.

How do I combine multiple objects into one?

To merge objects into a new one that has all properties of the merged objects, you have two options: Use a spread operator ( ... ) Use the Object. assign() method.


2 Answers

Decode each JSON string into an associative array, merge the results and re-encode

$a1 = json_decode( $json1, true );
$a2 = json_decode( $json2, true );

$res = array_merge_recursive( $a1, $a2 );

$resJson = json_encode( $res );

Update: If you have a specific merge requirement then you'll need to write your own merging function. I have written one below which fulfills your requirements as stated in the question. You may need to tweak it if you have other requirements you haven't mentioned.

<?php

$json1 = '
{
    "blah":
    {
        "params":
        {
            "foo":
            {
                "default": "bar",
                "misc": "0"
            }
        },
        "lost":
        {
            "one": "hat",
            "two": "cat"
        }
    }
}';

$json2 = '
{
    "blah":
    {
        "lost": "gone",
        "params":
        {
            "foo":
            {
                "value": "val",
                "misc": "1"
            }
        }
    },
    "num_array": [12, 52, 38]
}';


$a1 = json_decode( $json1, true );
$a2 = json_decode( $json2, true );


/*
 * Recursive function that merges two associative arrays
 * - Unlike array_merge_recursive, a differing value for a key
 *   overwrites that key rather than creating an array with both values
 * - A scalar value will overwrite an array value
 */
function my_merge( $arr1, $arr2 )
{
    $keys = array_keys( $arr2 );
    foreach( $keys as $key ) {
        if( isset( $arr1[$key] ) 
            && is_array( $arr1[$key] ) 
            && is_array( $arr2[$key] ) 
        ) {
            $arr1[$key] = my_merge( $arr1[$key], $arr2[$key] );
        } else {
            $arr1[$key] = $arr2[$key];
        }
    }
    return $arr1;
}


$a3 = my_merge( $a1, $a2);
$json3 = json_encode( $a3 );
echo( $json3 );

/*
{
    "blah":
    {
        "params":
        {
            "foo":
            {
                "default": "bar",
                "misc":    "1",
                "value":   "val"
            }
        },
        "lost": "gone"
    },
    "num_array": [12,52,38]
}
*/
like image 78
meouw Avatar answered Sep 18 '22 05:09

meouw


Use array-replace-recursive() http://www.php.net/manual/en/function.array-replace-recursive.php
It does exactly what you want.

like image 36
TermoTux Avatar answered Sep 19 '22 05:09

TermoTux