如何在Laravel中使用JSONSchemaGenerator附加*如果数组中有多个重复对象 [英] How can attach * if multiple repeat object in array using JSONSchemaGenerator in laravel
问题描述
我从 json 生成架构时遇到问题,如果它们在array/json中重复出现,则不会附加多个对象/数组,例如(venue_id,total_users,unique_users,unique_percentage).我已经尝试了很多次,但是失败了.数据可以具有任何类型的API响应. json可能是这样的. https://jsoneditoronline.org/?id=7565670384c371680feee168d7db882e
I have problem when i generate the schema from json it is not attach with multiple object/array like (venue_id,total_users,unique_users,unique_percentage) if they are repeat in array/json. I have try many times but fail. Data may have any type of API response. json may be like this. https://jsoneditoronline.org/?id=7565670384c371680feee168d7db882e
我的json格式如下:
{
"venues_details": {
"frequency": "27%",
"all_venue_details": [
{
"venue_id": "15",
"total_users": "0",
"unique_users": "0",
"unique_percentage": "0%"
},
{
"venue_id": "16",
"total_users": "59",
"unique_users": "42",
"unique_percentage": "71%"
},
{
"venue_id": "17",
"total_users": "595",
"unique_users": "94",
"unique_percentage": "15%"
}
]
}
}
我的代码:
<?php
use JSONSchemaGenerator\Generator;
protected function convertSchemaToJson( $json_data )
{
$json_data = json_decode($json_data);
$data = [];
foreach ($json_data->properties as $key => $value) {
if ($value->type == "object") {
$this->traverseObject($value->properties,$key);
$data = array_merge( $data, $this->treeData );
$this->treeData = [];
$this->keyString = '';
} elseif ($value->type == "array") {
foreach ($value->items->anyOf as $k => $v) {
if ($v->type == "object") {
$this->traverseObject($v->properties, $key);
$data = array_merge( $data, $this->treeData );
$this->treeData = [];
$this->keyString = '';
} else {
$data[$key] = ['type' => $v->type];
}//..... end if() .....//
}//..... end foreach() ......//
} else {
$data[$key] = ['type' => $value->type];
}//..... end if-else .....//
}//..... end foreach() .....//
return $data;
}//..... end of convertSchemaToJson() .....//
private function traverseObject( $object, $key )
{
foreach ($object as $k => $v) {
$this->keyString .= !$this->keyString ? $key : ".".$key;
if ($v->type == "object") {
$this->traverseObject($v->properties, $k);
} elseif ($v->type == "array") {
foreach ($v->items->anyOf as $index => $val) {
if ($val->type == "object") {
if( !$this->retainedKey )
$this->retainedKey = $this->keyString;
$this->traverseObject($val->properties, $k);
} /*else {
$this->treeData[ $this->keyString.".".$k ] = ['type' => $val->type];
$this->keyString = $k;
}*/
$this->retainedKey = "";
}//..... end foreach() ......//
} else {
$this->treeData[ $this->keyString.".".$k ] = ['type' => $v->type];
$this->keyString = $this->retainedKey ? $this->retainedKey : "";
}//..... end if() .....//
}//..... end foreach() ......//
return;
}//..... end of traverseObject() .....//
protected function generateJsonSchemaFromJson( $data )
{
$data = str_replace('null', '""', $data);
return Generator::fromJson( $data );
}//..... end of generateJsonSchemaFromJson() .....//
$data = '{
"venues_details": {
"frequency": "27%",
"name": "location area",
"all_venue_details": [
{
"venue_id": "15",
"total_users": "0",
"unique_users": "0",
"unique_percentage": "0%"
},
{
"venue_id": "16",
"total_users": "59",
"unique_users": "42",
"unique_percentage": "71%"
},
{
"venue_id": "17",
"total_users": "595",
"unique_users": "94",
"unique_percentage": "15%"
}
]
}
}';
$schema = Generator::fromJson( $data );
$mapperJsonArr = $this->convertSchemaToJson($schema);
print_r($mapperJsonArr);
?>
我的输出:
[
"venues_details.frequency" => [
"type" => "string"
],
"venues_details.all_venue_details.*venue_id" => [
"type" => "string"
],
"venues_details.all_venue_details.*total_users" => [
"type" => "string"
],
"venues_details.all_venue_details.*unique_users" => [
"type" => "string"
],
"venues_details.all_venue_details.*unique_percentage" => [
"type" => "string"
]
]
预期输出应为:
[
"venues_details.frequency" => [
"type" => "string"
],
"venues_details.*all_venue_details.venue_id" => [
"type" => "string"
],
"venues_details.*all_venue_details.total_users" => [
"type" => "string"
],
"venues_details.*all_venue_details.unique_users" => [
"type" => "string"
],
"venues_details.*all_venue_details.unique_percentage" => [
"type" => "string"
]
]
请帮助!
推荐答案
我将其重写为单个递归函数,而不是调试现有代码,该递归函数更易于阅读:
Rather than debug the existing code, I rewrote it as a single recursive function that is much easier to read:
function objToSchema($obj, &$branches, $branch=NULL) {
foreach ((Array)$obj AS $name=>$elem) {
switch (gettype($elem)) {
case 'object':
// Recurse!
objToSchema($elem, $branches, (!is_numeric($name) ? $branch.($branch?'.':'').$name : $branch));
break;
case 'array':
// Recurse!
objToSchema($elem, $branches, (!is_numeric($name) ? $branch.($branch?'.':'').'*'.$name : $branch));
break;
case 'integer':
case 'string':
case 'double':
// This is a value node. Prepare the final path and store the datatype in array
$final = $branch.($branch?'.':'').$name;
if (!in_array($final, array_keys($branches)))
$branches[$final] = ['type' => gettype($elem)];
break;
}
}
}
调用:
$branches = [];
objToSchema(json_decode($sourceJson), $branches);
执行后,var_dump($branches)
输出:
array(5) {
["venues_details.frequency"]=>
array(1) {
["type"]=>
string(6) "string"
}
["venues_details.*all_venue_details.venue_id"]=>
array(1) {
["type"]=>
string(6) "string"
}
["venues_details.*all_venue_details.total_users"]=>
array(1) {
["type"]=>
string(6) "string"
}
["venues_details.*all_venue_details.unique_users"]=>
array(1) {
["type"]=>
string(6) "string"
}
["venues_details.*all_venue_details.unique_percentage"]=>
array(1) {
["type"]=>
string(6) "string"
}
}
这篇关于如何在Laravel中使用JSONSchemaGenerator附加*如果数组中有多个重复对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!