You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP多维数组转JSON对象:新旧JSON结构匹配问题求助

PHP 7.4 动态生成数组匹配旧JSON结构问题

PHP新手 [PHP 7.4]

正在重构旧代码,目标:两份JSON必须完全匹配,用PHPUnit做对比测试。

问题:新的动态生成代码输出的JSON比旧代码多了一组方括号;尝试用JSON_FORCE_OBJECT参数,虽移除了方括号,但引入了多余的数字键(如john下的"0"、marie下的"1")。


旧代码(代码片段1)

PHP数组代码

$body = [
    "data" => [
        "john" => [
            "byEmail" => [
                "status" => true,
                "source" => "my-server",
            ],
            "byPhoneCall" => [
                "status" => true,
                "source" => "my-server",
            ]
        ],
        "marie" => [
            "byEmail" => [
                "status" => true,
                "source" => "my-server",
            ],
            "byPhoneCall" => [
                "status" => true,
                "source" => "my-server",
            ]
        ]
    ]
];

执行json_encode()后的JSON结果

{
    "data": {
        "john": {
            "byEmail": {
                "source": "my-server",
                "status": true
            },
            "byPhoneCall": {
                "source": "my-server",
                "status": true
            }
        },
        "marie": {
            "byEmail": {
                "source": "my-server",
                "status": true
            },
            "byPhoneCall": {
                "source": "my-server",
                "status": true
            }
        }
    }
}

动态生成代码(代码片段2)

为了支持未来新增字段(如johnByPost、johnByFax等),采用动态方式构建数组:

//my-file-dynamic-generation.php

public function constructArray($johnByEmail=null, $johnByPhone=null, $marieByEmail=null, $marieByPhone=null) {
    $body = [ "data" => ["john" => [], "marie" => []]];

    if ($johnByEmail !== null) {
        array_push($body["data"]["john"], $this->createKeyValuePair("byEmail", $johnByEmail));
    }

    if ($johnByPhone !== null) {
        array_push($body["data"]["john"], $this->createKeyValuePair("byPhoneCall", $johnByPhone));
    }

    if ($marieByEmail !== null) {
        array_push($body["data"]["marie"], $this->createKeyValuePair("byEmail", $marieByEmail));
    }

    if ($marieByPhone !== null) {
        array_push($body["data"]["marie"], $this->createKeyValuePair("byPhoneCall", $marieByPhone));
    }
    return $body;
}

// 辅助函数
function createKeyValuePair($title=null, $status=null, $source="my-server") {
    return [
        $title => [
            "status" => $status,
            "source" => $source,
        ]
    ];
}

问题根源

createKeyValuePair返回的是包含单个键值对的数组,再通过array_push将这些数组添加到john/marie的数组中,最终john变成了数组的数组(如[[byEmail: {...}], [byPhoneCall: {...}]]),json_encode后就会生成带方括号的JSON数组;而旧代码中john是关联数组,编码后是JSON对象(花括号)。

用JSON_FORCE_OBJECT会把数组强制转为对象,但会保留原数组的数字索引(0、1等),导致出现多余键。


解决方案

方案一:修改数组赋值方式,合并关联数组

不需要用array_push,而是将createKeyValuePair返回的数组直接合并到john/marie的关联数组中:

public function constructArray($johnByEmail=null, $johnByPhone=null, $marieByEmail=null, $marieByPhone=null) {
    $body = [ "data" => ["john" => [], "marie" => []]];

    if ($johnByEmail !== null) {
        $body["data"]["john"] = array_merge($body["data"]["john"], $this->createKeyValuePair("byEmail", $johnByEmail));
    }

    if ($johnByPhone !== null) {
        $body["data"]["john"] = array_merge($body["data"]["john"], $this->createKeyValuePair("byPhoneCall", $johnByPhone));
    }

    if ($marieByEmail !== null) {
        $body["data"]["marie"] = array_merge($body["data"]["marie"], $this->createKeyValuePair("byEmail", $marieByEmail));
    }

    if ($marieByPhone !== null) {
        $body["data"]["marie"] = array_merge($body["data"]["marie"], $this->createKeyValuePair("byPhoneCall", $marieByPhone));
    }
    return $body;
}

方案二:修改辅助函数,直接返回键值内容

让createKeyValuePair返回byEmail/byPhoneCall对应的内部数组,直接赋值给关联数组的键:

// 修改辅助函数
function createKeyValuePair($status=null, $source="my-server") {
    return [
        "status" => $status,
        "source" => $source,
    ];
}

// 修改constructArray方法
public function constructArray($johnByEmail=null, $johnByPhone=null, $marieByEmail=null, $marieByPhone=null) {
    $body = [ "data" => ["john" => [], "marie" => []]];

    if ($johnByEmail !== null) {
        $body["data"]["john"]["byEmail"] = $this->createKeyValuePair($johnByEmail);
    }

    if ($johnByPhone !== null) {
        $body["data"]["john"]["byPhoneCall"] = $this->createKeyValuePair($johnByPhone);
    }

    if ($marieByEmail !== null) {
        $body["data"]["marie"]["byEmail"] = $this->createKeyValuePair($marieByEmail);
    }

    if ($marieByPhone !== null) {
        $body["data"]["marie"]["byPhoneCall"] = $this->createKeyValuePair($marieByPhone);
    }
    return $body;
}

两种方案都能让john/marie成为正确的关联数组,json_encode后生成与旧代码完全一致的JSON对象,不会出现多余的方括号或数字键。


内容的提问来源于stack exchange,提问作者Rashedul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 17:01:10