使用PHP创建包含JSON的数据的JSON

时间:2016-11-13 16:11:43

标签: php json

如何使用PHP创建包含JSON的数据的JSON,而不在JSON中包含一堆转义字符,并且不首先将JSON转换为数组或对象,然后再转换回JSON?

<?php
/*
GIVEN: Data from DB contained in array $a.
I know that sometimes JSON shouldn't be stored in a DB, but please assume this is a good case for doing so.
*/
$a[0]=json_encode(['a'=>5,'b'=>'hello']);
$a[1]=json_encode(['a'=>2,'b'=>'how are you']);
$a[2]=json_encode(['a'=>7,'b'=>'goodby']);

$o=[
    ['x'=>321,'y'=>$a[0]],
    ['x'=>123,'y'=>$a[1]],
    ['x'=>111,'y'=>$a[2]],
];

echo('<pre>'.print_r($o,1).'</pre>');
echo(json_encode($o));
/*
Undesired result containing a bunch of escape characters.  Granted, they are benign, however, will increase network trafic.
[{"x":321,"y":"{\"a\":5,\"b\":\"hello\"}"},{"x":123,"y":"{\"a\":2,\"b\":\"how are you\"}"},{"x":111,"y":"{\"a\":7,\"b\":\"goodby\"}"}]
*/

$o=[
    ['x'=>321,'y'=>json_decode($a[0])],
    ['x'=>123,'y'=>json_decode($a[1])],
    ['x'=>111,'y'=>json_decode($a[2])],
];

echo('<pre>'.print_r($o,1).'</pre>');
echo(json_encode($o));
/*
Desired result, however, is there a more efficient way to do this?
[{"x":321,"y":{"a":5,"b":"hello"}},{"x":123,"y":{"a":2,"b":"how are you"}},{"x":111,"y":{"a":7,"b":"goodby"}}]
*/

1 个答案:

答案 0 :(得分:0)

不,没有更快的方法可以再次进行解码,变异和编码。

然而,您可以将解码代码与数据库查询紧密结合。如果你有一个数据模型类,你可以在那里进行解码,这样调用这个服务的代码永远不会看到JSON,但总是看到解码后的数据。

然后,再次,在您写入数据库的数据模型中,您将在最后一刻执行JSON编码。

这样您就可以隐藏数据层墙后面的JSON因子,而应用程序的其余部分则不必了解它。

直接操作JSON

另一种解决方案包括编写一个可以兼顾JSON的库,提供在JSON中设置值的可能性,而不需要调用者解码/编码。此选项需要更多代码(或者您可以找到现有库),因此这不是我的第一个建议。但这是一个可以存在于该库中的函数的简单示例:

function json_set($json, $path, $value) {
    $arr = json_decode($json, true);
    $ref =& $arr;
    $props = explode("/", $path);
    $finalProp = array_pop($props);
    foreach ($props as $key) {
        if (!isset($ref[$key])) $ref[$key] = [];
        $ref =& $ref[$key];
    }
    $obj = json_decode($value);
    $ref[$finalProp] = $obj ? $obj : $value;
    return json_encode($arr);
}

这允许您提供现有的JSON字符串,指向该JSON内某个点的路径,以及应该放在那里的值。该值本身也可以是JSON。

根据您从数据库中获取的 $ a 中的JSON值,以下是如何在您的情况下使用它:

$o=json_encode([
    ['x'=>321],
    ['x'=>123],
    ['x'=>111],
]);

$o = json_set($o, '0/y', $a[0]);
$o = json_set($o, '1/y', $a[1]);
$o = json_set($o, '2/y', $a[2]);

echo $o;

输出:

[{"x":321,"y":{"a":5,"b":"hello"}},
 {"x":123,"y":{"a":2,"b":"how are you"}},
 {"x":111,"y":{"a":7,"b":"goodby"}}]