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
相关产品推荐
相关产品推荐

