Подтвердить что ты не робот

Объединение двух сложных объектов в PHP

У меня есть два объекта данных, преобразованные из JSON. оба довольно сложны, и я хотел бы объединить их так же, как jQuery объединил бы два объекта, используя расширение.

Пример

JSON 1:

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

JSON 2:

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

Слияние в

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

Какой лучший способ приблизиться к объектам PHP.

4b9b3361

Ответ 1

Декодировать каждую строку JSON в ассоциативный массив, объединять результаты и перекодировать

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

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

$resJson = json_encode( $res );

Update: Если у вас есть конкретное требование слияния, вам нужно написать свою собственную функцию слияния. Я написал один ниже, который соответствует вашим требованиям, указанным в вопросе. Возможно, вам придется настроить его, если у вас есть другие требования, о которых вы не упомянули.

<?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]
}
*/

Ответ 3

Небольшое улучшение кода @meouw (выше) позволяет объединять индексированные массивы в объектах.

$a = '{ "things": ["abc"], "apple":"pear" }';
$b = '{ "things": ["123"] }';

$a1 = json_decode( $a, true );
$b1 = json_decode( $b, true );

echo json_encode(deep_merge($a1,$b1));
// output: {"things":["abc","123"],"apple":"pear"}

function deep_merge( $arr1, $arr2 )
{
    $keys = array_keys( $arr2 );
    foreach( $keys as $key ) {
        if (isset($arr1[$key]) && is_numeric($key) ) {
            array_push($arr1,$arr2[$key]);
        }
        else if( isset($arr1[$key]) && is_array($arr1[$key]) && is_array($arr2[$key])) {
            $arr1[$key] = deep_merge( (array)$arr1[$key],(array) $arr2[$key] );
        } else {
            $arr1[$key] = $arr2[$key];
        }
    }
    return $arr1;
}

В противном случае вывод будет {"things":["123"],"apple":"pear"}

пример