取消转义字符串 JSON 嵌套在 JSON 中 PHP
Unescaping a string meant to be JSON nested in JSON in PHP
我的服务器从真实设备接收 JSON 数据,然后将其保存在 MySQL JSON 字段中。不幸的是,制造商的代码中似乎有一个错误,导致部分数据被字符串化转义 JSON.
[
"foo",
"bar",
"info",
{
"data": "{\"parts\":[{\"id\":1,\"serial\":\"19777\",\"type\":\"NONE\",\"key\":\"\"}]}",
"vendor": "Test",
"message": "Hello world"
}
]
运行 json_decode
即使 JSON_UNESCAPED_SLASHES
也会导致字符串
Array
(
[0] => foo
[1] => bar
[2] => info
[3] => Array
(
[data] => {"parts":[{"id":1,"serial":"19777","type":"NONE","key":""}]}
[vendor] => Test
[message] => Hello world
)
)
但预期的输出是
Array
(
[0] => foo
[1] => bar
[2] => info
[3] => Array
(
[data] => Array
(
[parts] => Array
(
[0] => Array
(
[id] => 1
[serial] => 19777
[type] => NONE
[key] =>
)
)
)
[vendor] => Test
[message] => Hellow world
)
)
因为我不能指望他们很快发布固件更新,有什么功能我可以 运行 在整个 JSON 上识别字符串化 JSON 并重新编码保存到 MySQL 之前的请求,但不会影响其他没有类似错误的消息?
更新:将 $json
内的任何嵌套 json 数据转换为关联数组:
使用函数 recurse()
遍历数组 $arr
,以查找具有 json 数据和 json_decode()
的任何元素以达到您的预期输出:
<?php
$arr = json_decode($json, true);
recurse($arr); // json_decode() any json inside $arr
function recurse(array &$arr)
{
foreach ($arr as $key => &$value) {
if (is_array($value)) {
recurse($value);
} else {
if (is_object(json_decode($value))) {
$value = json_decode($value, true); // turn json into assoc array
}
}
}
}
工作demo
快速解决方案:
$full_array = array_map('json_decode', $array);
如果不是所有参数都是 JSON,并且您想要实际数组而不是 stdClass 对象,您可能必须这样做:
function json_decode_array($input) {
$from_json = json_decode($input, true);
return $from_json ? $from_json : $input;
}
$full_array = array_map('json_decode_array', $array);
主要答案:
Google: php json_decode 递归
如果主要关注的是“数据”字段,这应该可行。
$json = '[
"foo",
"bar",
"info",
{
"data": "{\"parts\":[{\"id\":1,\"serial\":\"19777\",\"type\":\"NONE\",\"key\":\"\"}]}",
"vendor": "Test",
"message": "Hello world"
},
{
"data": {"parts":[{"id":1,"serial":"19777","type":"NONE","key":""}]},
"vendor": "Test",
"message": "Hello world"
}
]';
$arr = json_decode($json, true);
$out = array();
foreach($arr as $a)
{
if(is_array($a))
{
if(!is_array($a['data']))
{
$a['data'] = json_decode($a['data'], true);
}
}
$out [] = $a;
}
print_r($out);
我的服务器从真实设备接收 JSON 数据,然后将其保存在 MySQL JSON 字段中。不幸的是,制造商的代码中似乎有一个错误,导致部分数据被字符串化转义 JSON.
[
"foo",
"bar",
"info",
{
"data": "{\"parts\":[{\"id\":1,\"serial\":\"19777\",\"type\":\"NONE\",\"key\":\"\"}]}",
"vendor": "Test",
"message": "Hello world"
}
]
运行 json_decode
即使 JSON_UNESCAPED_SLASHES
也会导致字符串
Array
(
[0] => foo
[1] => bar
[2] => info
[3] => Array
(
[data] => {"parts":[{"id":1,"serial":"19777","type":"NONE","key":""}]}
[vendor] => Test
[message] => Hello world
)
)
但预期的输出是
Array
(
[0] => foo
[1] => bar
[2] => info
[3] => Array
(
[data] => Array
(
[parts] => Array
(
[0] => Array
(
[id] => 1
[serial] => 19777
[type] => NONE
[key] =>
)
)
)
[vendor] => Test
[message] => Hellow world
)
)
因为我不能指望他们很快发布固件更新,有什么功能我可以 运行 在整个 JSON 上识别字符串化 JSON 并重新编码保存到 MySQL 之前的请求,但不会影响其他没有类似错误的消息?
更新:将 $json
内的任何嵌套 json 数据转换为关联数组:
使用函数 recurse()
遍历数组 $arr
,以查找具有 json 数据和 json_decode()
的任何元素以达到您的预期输出:
<?php
$arr = json_decode($json, true);
recurse($arr); // json_decode() any json inside $arr
function recurse(array &$arr)
{
foreach ($arr as $key => &$value) {
if (is_array($value)) {
recurse($value);
} else {
if (is_object(json_decode($value))) {
$value = json_decode($value, true); // turn json into assoc array
}
}
}
}
工作demo
快速解决方案:
$full_array = array_map('json_decode', $array);
如果不是所有参数都是 JSON,并且您想要实际数组而不是 stdClass 对象,您可能必须这样做:
function json_decode_array($input) {
$from_json = json_decode($input, true);
return $from_json ? $from_json : $input;
}
$full_array = array_map('json_decode_array', $array);
主要答案:
Google: php json_decode 递归
如果主要关注的是“数据”字段,这应该可行。
$json = '[
"foo",
"bar",
"info",
{
"data": "{\"parts\":[{\"id\":1,\"serial\":\"19777\",\"type\":\"NONE\",\"key\":\"\"}]}",
"vendor": "Test",
"message": "Hello world"
},
{
"data": {"parts":[{"id":1,"serial":"19777","type":"NONE","key":""}]},
"vendor": "Test",
"message": "Hello world"
}
]';
$arr = json_decode($json, true);
$out = array();
foreach($arr as $a)
{
if(is_array($a))
{
if(!is_array($a['data']))
{
$a['data'] = json_decode($a['data'], true);
}
}
$out [] = $a;
}
print_r($out);