如何将PHP数组转换为JSON格式但保留键名不带双引号

23

我正在尝试使用Flot绘制带有一些数据的饼图

var data = <?php echo json_encode($data)?>

我从中得到的结果是这样的:

var data = [
{"label":"Crear Usuario", "data":"2"},
{"label":"Impresoras", "data":"1"},
{"label":"Problema Correo", "data":"1"},
{"label":"Requisicion Equipo", "data":"1"},
{"label":"Sitio Web", "data":"1"}
]

这里的问题是我需要没有引号的,我已经尝试了json_encode($data, JSON_NUMERIC_CHECK);,但只能去掉数字的引号。

以下是我需要的格式:

var data = [
    {label:"Crear Usuario",data:2}, ...

你想用 PHP 进行转换吗? - Mohit Mehta
我认为用PHP进行转换会更好。 - Danny
2
为什么你想要没有引号的格式?有或者没有引号是等效的(虽然没有引号就不是JSON)。 - Musa
@Musa:这就是Flot需要格式化对象的方式 :/ - Danny
我非常确定问题在其他地方。 - Ja͢ck
我认为Flot无法确定你的对象是否使用引号创建键。 - Musa
5个回答

14

首先,您需要在PHP中生成数组,以便数据的值为整数而不是字符串:

我从您的json_encode()模拟了您的数组,我猜它看起来像这样(或者应该是这样):

$array =  array(
                array("label" => "Crear Usuario",   "data" => 2),
                array("label" => "Impresoras",      "data" => 1),
                array("label" => "Problema Correo", "data" => 1),
                array("label" => "Requisicion Equipo", "data" => 1),
                array("label" => "Sitio Web", "data" => 1)
            );

    $data = json_encode($array);
  • 注意2和1是未加引号的,因此它们是整数,这一点很重要。

然后在JavaScript中你需要使用JSON.parse()来将输出转换成JSON对象:

<script>
    var data = '<?php echo $data; ?>';
    var json = JSON.parse(data);
    console.log(json);
    console.log(json[0]);
</script>
  • 请注意 var data = ... 是用单引号括起来的,这样你就可以将php输出的内容作为字符串捕获

控制台输出如下:

[Object, Object, Object, Object, Object] // First console.log(): one object with the 5 Objects. 
Object {label: "Crear Usuario", data: 2} // secons console log (json[0]) with the first object 

看起来这正是你需要的,我说得对吗?


1
只有 var data = <?php echo $data; ?>;(去掉单引号)才能做完全相同的事情 - 而不需要在客户端解析。 - Yaron U.

8

引号和未引号的键之间没有区别。问题在于实际数据值周围的引号,因为Flot需要数字而不是字符串。

json_encode函数根据您提供给它的数据类型来决定是否加引号。在这种情况下,似乎您执行的任何操作都会产生字符串值而不是整数。您需要重新检查这些操作,或者明确告诉PHP将它们解释为数字,使用(int)或(float)强制转换,或intval/floatval函数。


4
试试这样做:
function buildBrokenJson( array $data ) {

   $result = '{';

   $separator = '';
   foreach( $data as $key=>$val ) {
      $result .= $separator . $key . ':';

      if( is_int( $val ) ) {
         $result .= $val;
      } elseif( is_string( $val ) ) {
         $result .= '"' . str_replace( '"', '\"', $val) . '"';
      } elseif( is_bool( $val ) ) {
         $result .= $val ? 'true' : 'false';
      } else {
         $result .= $val;
      }

      $separator = ', ';
   }

   $result .= '}';

   return $result;
}

并且当运行时

$a = array("string"=>'Crear "Usuario', 'foo'=>':', "int"=>2, "bool"=>false);
var_dump( buildBrokenJson($a) );

它提供:

string(54) "{string:"Crear \"Usuario", foo:":", int:2, bool:false}"

我想要单词"label"(不带引号),以及"data"。 - Danny
1
这些是字符串类型。将会被引用。你可以编写自己的json_encode - 这不难(我现在在手机上)。 - Marcin Orlowski

3
我创建了一个类,用php格式化json并去除键名的引号,这是它的代码:
class JsonFormatter
{
static $result = '';
static $separator = '';

public static function iterateArray($data) : string
{
    static::$result .= '[';
    static::$separator = '';
    foreach ($data as $key => $val) {
        if (is_int($val)) {

        } elseif (is_string($val)) {
            static::$result .= '"' . str_replace('"', '\"', $val) . '"';
        } elseif (is_bool($val)) {
            static::$result .= $val ? 'true' : 'false';
        } elseif (is_object($val)) {
            static::iterateObject($val);
            static::$result .= ', ';
        } elseif (is_array($val)) {
            static::iterateArray($val);
            static::$result .= ', ';
        } else {
            static::$result .= $val;
        }
        if (!is_int($val)) {
            static::$separator = ', ';
        }
    }

    static::$result .= ']';
    return static::$result;
}

public static function iterate($data)
{
    if (is_array($data)) {
        static::iterateArray($data);
    } elseif (is_object($data)) {
        static::iterateObject($data);
    }
    return static::$result;
}

public static function iterateObject($data)
{
    static::$result .= '{';
    static::$separator = '';
    foreach ($data as $key => $val) {

        static::$result .= static::$separator . $key . ':';

        if (is_int($val)) {
            static::$result .= $val;
        } elseif (is_string($val)) {
            static::$result .= '"' . str_replace('"', '\"', $val) . '"';
        } elseif (is_bool($val)) {
            static::$result .= $val ? 'true' : 'false';
        } elseif (is_object($val)) {
            static::iterate($val, true);
            static::$result .= ', ';
        } elseif (is_array($val)) {
            static::iterateArray($val, true);
            static::$result .= ', ';
        } else {
            static::$result .= $val;
        }
        static::$separator = ', ';
    }
    static::$result .= '}';
    return static::$result;
}

}

你现在可以调用

$jsonWithoutKeyQuotes  = JsonFormatter::iterate($data);

感谢Marcin Orlowski的贡献。

有一个小问题,这个函数在新属性之前的最后一个闭合括号后面添加了一个额外的逗号。你能快速修复一下吗?尝试使用相当深的对象进行测试。谢谢。 - Jason Engage

0

TL;DR:缺少引号是Chrome展示JSON对象而不是字符串的方式。确保在PHP的AJAX响应中使用Header('Content-Type: application/json; charset=UTF8')来解决真正的问题。

详细信息: 想要解决这个问题的常见原因是在调试返回的AJAX数据时发现了这个差异。

在我的情况下,我使用Chrome的调试工具看到了这个差异。当连接到旧系统时,在成功后,Chrome显示响应中键周围没有引号。根据调试器,这使得对象可以立即视为一个对象,而无需使用JSON.parse()调用。在调试新的AJAX目标时,响应中有引号并且变量是字符串而不是对象。
当我在外部测试AJAX响应时,最终意识到了真正的问题,发现旧系统实际上确实在键周围有引号。这与Chrome开发工具所显示的不同。 唯一的区别是旧系统上有一个指定内容类型的标头。我将其添加到新(WordPress)系统中,现在调用完全兼容原始脚本,成功函数可以处理响应作为对象而不需要任何解析。现在我可以在旧系统和新系统之间切换而不需要进行任何更改,除了目标URL。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接