【问题标题】:Why do php function json_decode fail if string contains the word undefined as a value?如果字符串包含单词 undefined 作为值,为什么 php 函数 json_decode 会失败?
【发布时间】:2011-05-31 08:53:16
【问题描述】:

我有这个字符串,它是由 dojo.toJson() 函数生成的:

{"page":"accommodation task=viewList","language":undefined}

在 php 中使用 json_decode 对其进行解码时,它返回 null。

我已经发现这是由未定义的值引起的,但我不确定这是预期的还是错误的。上面的字符串不是有效的json吗?为什么php不能直接将undefined转为null?

我使用的是 PHP 5.2.10

【问题讨论】:

  • 如果它是 dojo 创建无效的 JSON 字符串,正如一些答案所建议的那样,可能值得注意的是我使用的是 dojo 1.4.3,所以这可能已在以后的版本中得到修复。 .?
  • 查看我的更新答案,它在 Dojo 1.6.1(最新)中仍然存在问题。

标签: php javascript json dojo


【解决方案1】:

因为undefined 无效JSON。 JSON 没有 undefined 的 JavaScript 概念。它确实有 null,它有点相似,但通常的事情(无论好坏)是简单地省略值为 undefined 的属性。

如果 Dojo 的 toJson 产生这样的无效 JSON,我会感到惊讶。您可以考虑改用Crockford's JSON.stringify。如果 Dojo 的 toJson 真的这样做,我会将其作为错误报告给 Dojo 团队。

更新:显然有人did report it to them,他们根据“垃圾进,垃圾出”理论将其关闭为无效。不是我的项目,但这完全是不是我将如何处理具有undefined 值的属性...我会忽略它们或抛出异常。

更新 2:您可能知道,ECMAScript 5th edition specification 定义了一个带有 parsestringifyJSON 对象,浏览器正在添加对这些对象的支持。规范对JSON.stringify 的定义说undefined 值未呈现”(第 15.12.3 节,注 2)——例如,应省略该属性。也许如果您向 Dojo 团队指出这一点,他们会重新考虑 GIGO 对错误报告的反应。还要注意下面@Felix 的评论:它们省略了函数引用,这也不能在 JSON 中有效表示,但对 undefined 应用不同的规则。

更新 3:在 Dojo 1.6.1 中仍然存在问题。这是 v1.6.0 的live test,它是 CDN 上的最新版本。我还测试了 v1.6.1,但它仍然在那里坏了。 (不过,不会发布指向他们的下载部分的测试页面热链接,那将是不礼貌的。)

【讨论】:

  • 谢谢,很好的答案。我正在使用 dojo 1.4.3,所以如果它没有在以后的版本中修复,我会考虑将其报告为错误。
  • @jgivoni:不用担心。我刚刚添加了引用新规范的更新,这可能会帮助您让他们修复它。
  • 这很有趣。这里似乎有某种双重标准。函数引用也无效,but omitted in the output。你是对的,undefined也应该这样做。
  • 我想这取决于未定义的值是否被正确地视为垃圾。由于它是 javascript (ecmascript) 的一部分,我希望不时遇到它。也许dojo会提供一个dojo.sanitizeForJson(),我们可以在每次使用dojo.toJson()之前应用它?不,我会先研究 Crockford 的 JSON.stringify :-)
  • @jgivoni:JavaScript 对象可以具有值为undefined 的属性或函数引用,这两者都是完全有效的。 JSON 没有代表这些东西。标准定义的行为是省略这些属性,并且该行为是在上面列出的错误报告之前定义的。此外,Crockford 的 JSON.stringify 省略了带有 undefined 值的属性,并且由于 Crockford defined JSON,在 ECMAScript 标准之前,他的实现将是确定的。出于对道场人的尊重,他们只是弄错了。 (有时我们都会这样做。)
【解决方案2】:

您可以在服务器端的 PHP 中将 undefined 转换为 null,从而解决眼前的问题:

<?php
$json = '{"page":"accommodation task=viewList","language":undefined,"example": "This is an example of an occurence of undefined that remains"}';
$json = preg_replace( 
     '~undefined(?=(?:[^"]*"[^"\\\\]*(?:\\\\.[^"\\\\]*)*")*[^"]*$)~', 'null', $json 
);

var_dump( json_decode( $json ) );

更好的解决方案是确保“未定义”不会出现在 JSON 中,因为它确实是无效的。

【讨论】:

  • ...如果“未定义”出现在带引号的字符串中?例如,{"msg": "The behavior shouldn't be undefined."} ;-)
  • 确实是好点。也许 str_replace 调用有点幼稚,而正则表达式会做得更好?
  • 祝你好运。众所周知,使用正则表达式难以处理转义的匹配引号。 :-) 正如您所说,最好的办法是首先防止这种情况发生。 (我会通过不使用 Dojo 的 toJson 来做到这一点。)
  • 呵呵,对我来说有点太大胆了,只是将所有出现的 'undefined' 替换为 'null' :-) 但是,如果你是鲁莽的类型......
  • @T.J. Crowder @jgivoni 修正了这一点,这不那么天真,并且不会替换任何出现在引号中的“未定义”。
猜你喜欢
  • 2017-01-07
  • 2018-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-13
  • 2020-05-24
相关资源
最近更新 更多