从 foreach 创建动态 JSON
Create dynamic JSON from foreach
我正在使用 jquery flot charts to represent my data. Here's the example JSFiddle 我制作的显示图表所需的 JSONS 的外观。
数据源来自具有以下输出示例的 MySql 存储过程:
我需要在图表中表示,y 轴上不同 innumber
堆叠的 count
值,x 轴上的 name
值,以及另一个图表,outnumber
的值。 (在堆叠条形图中)。
-数据系列应匹配,因此特定标签应针对客户显示。
这是我目前的PHP:
$query = $this->db->query("call GetAllCustomersV2($id, $year, $month, $day)");
$customers = $query->result_array();
foreach ($customers as $customer) {
if($customer['innumber'] != null){
$chartInbound['name'] = $customer['name'];
$chartInbound['label'] = $customer['innumber'];
$chartInbound['count'] = $customer['count'];
$chartInbound['customerid'] = $customer['id'];
array_push($out['chartInbound'], $chartInbound);
}
if($customer['outnumber'] != null){
$chartOutbound['name'] = $customer['name'];
$chartOutbound['label'] = $customer['outnumber'];
$chartOutbound['count'] = $customer['count'];
$chartOutbound['customerid'] = $customer['id'];
array_push($out['chartOutbound'], $chartOutbound);
}
}
print_r($out['chartInbound']);
的输出是:
Array
(
[0] => Array
(
[name] => 1st Online Solutions
[label] => 01-02
[count] => 577
[customerid] => 129
)
[1] => Array
(
[name] => Bookngo
[label] => 01-02
[count] => 2
[customerid] => 95
)
[2] => Array
(
[name] => Boutixury
[label] => 07
[count] => 1
[customerid] => 14
)
[3] => Array
(
[name] => Cruise Village
[label] => 01-02
[count] => 16
[customerid] => 25
)
[4] => Array
(
[name] => Cruise Village
[label] => 00
[count] => 1
[customerid] => 25
)
[5] => Array
(
[customer] => Cruise Village
[label] => 07
[countInbound] => 16
[minsInbound] => 125
[customerid] => 25
)
...................
)
print_r(json_encode($out['chartInbound']));
的输出是:
[
{
"name": "1st Online Soultions"
"label": "01-02",
"count": "577",
"customerid": "129"
},
{
"name": "Bookngo"
"label": "01-020",
"count": "2",
"customerid": "129"
},
{
"name": "Boutixury"
"label": "07",
"count": "1",
"customerid": "14"
},
{
"name": "Cruise Village"
"label": "07",
"count": "16",
"customerid": "25"
},
.................
]
但这不是很有帮助。
问: 如何根据查询数据创建上面 jsfiddle 中显示的动态 JSON?
您将不得不自己改造结构。您可以在服务器端或客户端执行此操作。在任一情况下 运行 通过结果构建您想要的结构。
小心尝试在 json 中编码 php 关联数组并注意 NUMERIC_CHECK.
的行为
您可以在客户端执行此操作(尽管理想情况下应该在服务器端执行),方法是使用类似以下内容:
var table = [
{name: 'a', label: 'l1', count: '15', customerid: '1'},
{name: 'a', label: 'l2', count: '1', customerid: '1'},
{name: 'a', label: 'l3', count: '7', customerid: '1'},
{name: 'b', label: 'l1', count: '3', customerid: '2'},
{name: 'b', label: 'l2', count: '9', customerid: '2'},
{name: 'b', label: 'l3', count: '2', customerid: '2'},
{name: 'c', label: 'l1', count: '1', customerid: '3'},
{name: 'c', label: 'l2', count: '7', customerid: '3'},
{name: 'a', label: 'l3', count: '5', customerid: '4'},
{name: 'a', label: 'l2', count: '6', customerid: '4'}
];
var customers = {};
var labels = {};
var i;
for (i = 0; i < table.length; ++i) {
customers[table[i].customerid] = table[i].name;
labels[table[i].label] = labels[table[i].label] || [];
labels[table[i].label].push([+table[i].customerid, +table[i].count]);
}
var chartData = [];
var chartTicks = [];
for (customer in customers) {
if (customers.hasOwnProperty(customer)) {
chartTicks.push([+customer, customers[customer]]);
}
}
for (label in labels) {
if (labels.hasOwnProperty(label)) {
chartData.push({label: label, data: labels[label]});
}
}
它解释了具有相同名称的不同客户(不同的客户 ID)(尽管 Flot 不会真正处理好),以及某些标签数据缺失的客户。将此逻辑转移到 PHP 并在服务器端执行应该不会太难。
编辑:
好的,我没有注意到它在有 labelID "gaps" 时表现得很奇怪。这是修改后的代码:
var table = [
{name: 'a', label: 'l1', count: '15', customerid: '1'},
{name: 'a', label: 'l2', count: '1', customerid: '1'},
{name: 'a', label: 'l3', count: '7', customerid: '1'},
{name: 'b', label: 'l1', count: '3', customerid: '2'},
{name: 'b', label: 'l2', count: '9', customerid: '2'},
{name: 'b', label: 'l3', count: '2', customerid: '2'},
{name: 'c', label: 'l1', count: '1', customerid: '3'},
{name: 'c', label: 'l2', count: '7', customerid: '3'},
{name: 'a', label: 'l3', count: '5', customerid: '7'},
{name: 'a', label: 'l2', count: '6', customerid: '7'}
];
var customers = {};
var labels = {};
var chartData = [];
var chartTicks = [];
var i;
var customerNo = 0;
for (i = 0; i < table.length; ++i) {
if(!customers.hasOwnProperty(table[i].customerid)) {
customers[table[i].customerid] = table[i].name;
chartTicks.push([customerNo, table[i].name]);
customerNo++;
}
labels[table[i].label] = labels[table[i].label] || [];
labels[table[i].label].push([customerNo - 1, +table[i].count]);
}
for (label in labels) {
if (labels.hasOwnProperty(label)) {
chartData.push({label: label, data: labels[label]});
}
}
标签 ID 按照它们在来自服务器的 table 中出现的顺序给出。 (虽然还是区分了两个同名不同customerID的客户)
循环遍历数据并构建 newData
和 newTicks
数组供 flot 使用:
var newData = [];
var newLabels = []; // only used to get index since newData has objects in it
var newTicks = [];
for (var i = 0; i < dataFromServer.length; i++) {
var datapoint = dataFromServer[i];
var tick = newTicks.indexOf(datapoint.name);
if (tick == -1) {
tick = newTicks.length;
newTicks.push(datapoint.name);
}
var index = newLabels.indexOf(datapoint.label);
if (index == -1) {
index = newLabels.length;
newLabels.push(datapoint.label);
newDataPoint = {
label: datapoint.label,
data: []
};
newDataPoint.data[tick] = [tick, datapoint.count];
newData.push(newDataPoint);
} else {
newData[index].data[tick] = [tick, datapoint.count];
}
}
for (var i = 0; i < newTicks.length; i++) {
newTicks[i] = [i, newTicks[i]];
}
newLabels = null;
我还必须更改您的工具提示生成,因为您的代码仅在所有数据系列完成并排序时才有效。现在也更简单了。
只是一个想法,我想您正在存储过程中使用分组依据。如果您可以修改它并添加一个 WITH ROLLUP,数据库将为您计算计数...请参阅 https://dev.mysql.com/doc/refman/5.0/en/group-by-modifiers.html 或搜索 SO 以获取建议
您在 chartTicks[i]
中的数据点似乎需要与 chartData[i].data
中的刻度顺序相匹配。
确保这种匹配的一种方法是在 sql 中按名称对数据进行排序,并在 php 中首先按客户堆叠结果,然后按标签堆叠结果。
$query = $this->db->query("call GetAllCustomersV2($id, $year, $month, $day)");
$customers = $query->result_array(); //should be sorted by name
$results = array();
foreach ($customers as $customer) {
$i = is_array($results[$customer['name']][$customer['innumber']])
? count($results[$customer['name']][$customer['innumber']])
: 0;
//stack data points by customer name first and label second
$results[$customer['name']][$customer['innumber']][] = array($i,$customer['count']);
}
$chartData = array();
$chartTicks = array();
$i=0;
foreach($results as $name => $labels) {
$chartTicks[] = array($i++,$name);
foreach($labels as $label => $data) {
$chartData[] = array(
'label' => $label,
'data' => $data,
);
}
}
print json_encode($chartData);
print json_encode($chartTicks);
这是将当前 JSON 数据结构转换为所需输出的简洁方法:
var reduced;
var chartData = Object.keys(reduced = data.reduce(function(a, b) {
if(a[b.label]) {
a[b.label].push([a[b.label].length, parseInt(b.count, 10)]);
} else {
a[b.label] = [[0, parseInt(b.count, 10)]];
}
return a;
}, {})).map(function(key) {
return {
label: key,
data: reduced[key]
};
});
Fiddle: http://jsfiddle.net/rdkgbteq/1/
如果您想转换服务器上的数据,PHP 中也有同样的内容:
$reduced = array_reduce($data, function($result, $current) {
if(array_key_exists($current['label'], $result)) {
array_push($result, [count($result[$current['label']]), $current['count']]);
} else {
$result[$current['label']] = [[0, $current['count']]];
}
return $result;
}, array());
$formatted = array_map(function($key) {
return array(
'label' => $key,
'data' => $reduced[$key]
);
}, array_keys($reduced));
echo json_encode($formatted);
如果你想让我详细说明这里发生的事情,请告诉我。
我正在使用 jquery flot charts to represent my data. Here's the example JSFiddle 我制作的显示图表所需的 JSONS 的外观。
数据源来自具有以下输出示例的 MySql 存储过程:
我需要在图表中表示,y 轴上不同 innumber
堆叠的 count
值,x 轴上的 name
值,以及另一个图表,outnumber
的值。 (在堆叠条形图中)。
-数据系列应匹配,因此特定标签应针对客户显示。
这是我目前的PHP:
$query = $this->db->query("call GetAllCustomersV2($id, $year, $month, $day)");
$customers = $query->result_array();
foreach ($customers as $customer) {
if($customer['innumber'] != null){
$chartInbound['name'] = $customer['name'];
$chartInbound['label'] = $customer['innumber'];
$chartInbound['count'] = $customer['count'];
$chartInbound['customerid'] = $customer['id'];
array_push($out['chartInbound'], $chartInbound);
}
if($customer['outnumber'] != null){
$chartOutbound['name'] = $customer['name'];
$chartOutbound['label'] = $customer['outnumber'];
$chartOutbound['count'] = $customer['count'];
$chartOutbound['customerid'] = $customer['id'];
array_push($out['chartOutbound'], $chartOutbound);
}
}
print_r($out['chartInbound']);
的输出是:
Array
(
[0] => Array
(
[name] => 1st Online Solutions
[label] => 01-02
[count] => 577
[customerid] => 129
)
[1] => Array
(
[name] => Bookngo
[label] => 01-02
[count] => 2
[customerid] => 95
)
[2] => Array
(
[name] => Boutixury
[label] => 07
[count] => 1
[customerid] => 14
)
[3] => Array
(
[name] => Cruise Village
[label] => 01-02
[count] => 16
[customerid] => 25
)
[4] => Array
(
[name] => Cruise Village
[label] => 00
[count] => 1
[customerid] => 25
)
[5] => Array
(
[customer] => Cruise Village
[label] => 07
[countInbound] => 16
[minsInbound] => 125
[customerid] => 25
)
...................
)
print_r(json_encode($out['chartInbound']));
的输出是:
[
{
"name": "1st Online Soultions"
"label": "01-02",
"count": "577",
"customerid": "129"
},
{
"name": "Bookngo"
"label": "01-020",
"count": "2",
"customerid": "129"
},
{
"name": "Boutixury"
"label": "07",
"count": "1",
"customerid": "14"
},
{
"name": "Cruise Village"
"label": "07",
"count": "16",
"customerid": "25"
},
.................
]
但这不是很有帮助。
问: 如何根据查询数据创建上面 jsfiddle 中显示的动态 JSON?
您将不得不自己改造结构。您可以在服务器端或客户端执行此操作。在任一情况下 运行 通过结果构建您想要的结构。 小心尝试在 json 中编码 php 关联数组并注意 NUMERIC_CHECK.
的行为您可以在客户端执行此操作(尽管理想情况下应该在服务器端执行),方法是使用类似以下内容:
var table = [
{name: 'a', label: 'l1', count: '15', customerid: '1'},
{name: 'a', label: 'l2', count: '1', customerid: '1'},
{name: 'a', label: 'l3', count: '7', customerid: '1'},
{name: 'b', label: 'l1', count: '3', customerid: '2'},
{name: 'b', label: 'l2', count: '9', customerid: '2'},
{name: 'b', label: 'l3', count: '2', customerid: '2'},
{name: 'c', label: 'l1', count: '1', customerid: '3'},
{name: 'c', label: 'l2', count: '7', customerid: '3'},
{name: 'a', label: 'l3', count: '5', customerid: '4'},
{name: 'a', label: 'l2', count: '6', customerid: '4'}
];
var customers = {};
var labels = {};
var i;
for (i = 0; i < table.length; ++i) {
customers[table[i].customerid] = table[i].name;
labels[table[i].label] = labels[table[i].label] || [];
labels[table[i].label].push([+table[i].customerid, +table[i].count]);
}
var chartData = [];
var chartTicks = [];
for (customer in customers) {
if (customers.hasOwnProperty(customer)) {
chartTicks.push([+customer, customers[customer]]);
}
}
for (label in labels) {
if (labels.hasOwnProperty(label)) {
chartData.push({label: label, data: labels[label]});
}
}
它解释了具有相同名称的不同客户(不同的客户 ID)(尽管 Flot 不会真正处理好),以及某些标签数据缺失的客户。将此逻辑转移到 PHP 并在服务器端执行应该不会太难。
编辑: 好的,我没有注意到它在有 labelID "gaps" 时表现得很奇怪。这是修改后的代码:
var table = [
{name: 'a', label: 'l1', count: '15', customerid: '1'},
{name: 'a', label: 'l2', count: '1', customerid: '1'},
{name: 'a', label: 'l3', count: '7', customerid: '1'},
{name: 'b', label: 'l1', count: '3', customerid: '2'},
{name: 'b', label: 'l2', count: '9', customerid: '2'},
{name: 'b', label: 'l3', count: '2', customerid: '2'},
{name: 'c', label: 'l1', count: '1', customerid: '3'},
{name: 'c', label: 'l2', count: '7', customerid: '3'},
{name: 'a', label: 'l3', count: '5', customerid: '7'},
{name: 'a', label: 'l2', count: '6', customerid: '7'}
];
var customers = {};
var labels = {};
var chartData = [];
var chartTicks = [];
var i;
var customerNo = 0;
for (i = 0; i < table.length; ++i) {
if(!customers.hasOwnProperty(table[i].customerid)) {
customers[table[i].customerid] = table[i].name;
chartTicks.push([customerNo, table[i].name]);
customerNo++;
}
labels[table[i].label] = labels[table[i].label] || [];
labels[table[i].label].push([customerNo - 1, +table[i].count]);
}
for (label in labels) {
if (labels.hasOwnProperty(label)) {
chartData.push({label: label, data: labels[label]});
}
}
标签 ID 按照它们在来自服务器的 table 中出现的顺序给出。 (虽然还是区分了两个同名不同customerID的客户)
循环遍历数据并构建 newData
和 newTicks
数组供 flot 使用:
var newData = [];
var newLabels = []; // only used to get index since newData has objects in it
var newTicks = [];
for (var i = 0; i < dataFromServer.length; i++) {
var datapoint = dataFromServer[i];
var tick = newTicks.indexOf(datapoint.name);
if (tick == -1) {
tick = newTicks.length;
newTicks.push(datapoint.name);
}
var index = newLabels.indexOf(datapoint.label);
if (index == -1) {
index = newLabels.length;
newLabels.push(datapoint.label);
newDataPoint = {
label: datapoint.label,
data: []
};
newDataPoint.data[tick] = [tick, datapoint.count];
newData.push(newDataPoint);
} else {
newData[index].data[tick] = [tick, datapoint.count];
}
}
for (var i = 0; i < newTicks.length; i++) {
newTicks[i] = [i, newTicks[i]];
}
newLabels = null;
我还必须更改您的工具提示生成,因为您的代码仅在所有数据系列完成并排序时才有效。现在也更简单了。
只是一个想法,我想您正在存储过程中使用分组依据。如果您可以修改它并添加一个 WITH ROLLUP,数据库将为您计算计数...请参阅 https://dev.mysql.com/doc/refman/5.0/en/group-by-modifiers.html 或搜索 SO 以获取建议
您在 chartTicks[i]
中的数据点似乎需要与 chartData[i].data
中的刻度顺序相匹配。
确保这种匹配的一种方法是在 sql 中按名称对数据进行排序,并在 php 中首先按客户堆叠结果,然后按标签堆叠结果。
$query = $this->db->query("call GetAllCustomersV2($id, $year, $month, $day)");
$customers = $query->result_array(); //should be sorted by name
$results = array();
foreach ($customers as $customer) {
$i = is_array($results[$customer['name']][$customer['innumber']])
? count($results[$customer['name']][$customer['innumber']])
: 0;
//stack data points by customer name first and label second
$results[$customer['name']][$customer['innumber']][] = array($i,$customer['count']);
}
$chartData = array();
$chartTicks = array();
$i=0;
foreach($results as $name => $labels) {
$chartTicks[] = array($i++,$name);
foreach($labels as $label => $data) {
$chartData[] = array(
'label' => $label,
'data' => $data,
);
}
}
print json_encode($chartData);
print json_encode($chartTicks);
这是将当前 JSON 数据结构转换为所需输出的简洁方法:
var reduced;
var chartData = Object.keys(reduced = data.reduce(function(a, b) {
if(a[b.label]) {
a[b.label].push([a[b.label].length, parseInt(b.count, 10)]);
} else {
a[b.label] = [[0, parseInt(b.count, 10)]];
}
return a;
}, {})).map(function(key) {
return {
label: key,
data: reduced[key]
};
});
Fiddle: http://jsfiddle.net/rdkgbteq/1/
如果您想转换服务器上的数据,PHP 中也有同样的内容:
$reduced = array_reduce($data, function($result, $current) {
if(array_key_exists($current['label'], $result)) {
array_push($result, [count($result[$current['label']]), $current['count']]);
} else {
$result[$current['label']] = [[0, $current['count']]];
}
return $result;
}, array());
$formatted = array_map(function($key) {
return array(
'label' => $key,
'data' => $reduced[$key]
);
}, array_keys($reduced));
echo json_encode($formatted);
如果你想让我详细说明这里发生的事情,请告诉我。