上次使用 json_decode() 解析从前端复制过来的json数据,发现怎么都解析不出来,查看json格式,发现没问题啊!
/*
注意:
之前碰过同样的问题,有可能是实体引起的!但那应该是针对从其他地方接收到的变量,而非是复制过来的字符串!
碰到这种问题,可以使用 html_entity_decode()
*/
下面黏贴下,我复制过的大概的字符串:
$str = "[{'name':'dongxuemin','age':30},{'name':'yangyaping','age':30}]";
反正让我看,我是真的看不出错误!
下面,揭晓答案:
上面的错误是:json字符串的格式不正确!
正确的是:
******
json中的 '键' 和 '值',都必须是双引号("),在json里只能用双引号表示字符串。
******
JSON字符串严格要求!!!说实话,没细看过json,我是真心不知道这个!上面的还是我花了不少时间测出来的。
先定义一个相同的数组:
$a = [
['name' => 'dongxuemin', 'age' => 30],
['name' => 'yangyaping', 'age' => 30],
];
echo json_encode($a); // 输出:[{"name":"dongxuemin","age":30},{"name":"yangyaping","age":30}]
然后和之前的字符串一个一个对比,整了好久的!
PHP手册的例子,有一个就指出了几个经常错误的原因:
<?php
// the following strings are valid JavaScript but not valid JSON(下面字符是有效的js字符串,但无效的JSON)
// the name and value must be enclosed in double quotes
// single quotes are not valid(对象的键和值,必须是 '双引号')
$bad_json = "{ 'bar': 'baz' }";
json_decode($bad_json); // null
// the name must be enclosed in double quotes(对象的键,必须使用双引号,js中可不添加引号,但json不可以)
$bad_json = '{ bar: "baz" }';
json_decode($bad_json); // null
// trailing commas are not allowed(最后面的 ',' 多余)
$bad_json = '{ bar: "baz", }';
json_decode($bad_json); // null
?>
找到问题后,就想对 JSON 稍微了解一点,就找了点文章看看:
具体就不总结了,有点晚。其实下面几篇文章总结的都不错(自己看下)
参考文章:
http://php.net/manual/zh/book.json.php(PHP文档的JSON扩展)
http://www.faqs.org/rfcs/rfc7159.html(PHP实现的JSON标准)
http://www.json.org/json-zh.html(JSON官网??)
http://www.ruanyifeng.com/blog/2009/05/data_types_and_json.html(阮一峰写的博客,真的是精辟!有时间应该全部拜读一遍!)
http://www.cnblogs.com/jamesbd/p/4185342.html
http://www.cnblogs.com/pinganzi/p/6229369.html
http://blog.csdn.net/leedaning/article/details/70210770
PHP官网的JSON,也了解了下:
4个函数:
json_encode($value [, $options = 0 [, $depth = 512]])
$value - 可以是除了 'resource' 类型外的其他7种类型
编码必须是 'UTF-8'
$options - 可以使用多个
JSON_HEX_QUOT -
JSON_HEX_TAG -
JSON_HEX_AMP -
...
我们平常说,编码中文,不乱码,可以使用 'JSON_UNESCAPED_UNICODE'
$depth - 设置最大深度(不用管)
json_decode($json [, $assoc = false [, $depth = 512 [, $options = []]]])
$json - 要解析的json字符串
编码必须是 'UTF-8'
$assoc - 是否返回关联数组,默认是false,表示返回对象(assoc - 从单词上就知道是 '关联' 意思)
$depth - 指定递归深度(不用管)
$options - 只有2个
JSON_BIGINT_AS_STRING - 用于将大整数转为字符串而非默认的float类型
JSON_OBJECT_AS_ARRAY - 与将assoc设置为 TRUE 有相同的效果(返回关联数组)
// 2个都是,返回json编码或解码时,最后发生的错误
json_last_error() // 返回的是 '错误码'
json_last_error_msg() // 返回的是 '错误详情'
// 错误码
JSON_ERROR_NONE - 无错误
JSON_ERROR_DEPTH - 到达了最大堆栈深度
JSON_ERROR_STATE_MISMATCH - 无效或异常的 JSON
JSON_ERROR_CTRL_CHAR - 控制字符错误,可能是编码不对
JSON_ERROR_SYNTAX - 语法错误
JSON_ERROR_UTF8 - 异常的 UTF-8 字符,也许是因为不正确的编码
... 还有更多,自己看文档 ...
JsonSerializable - JSON序列化接口
/*
注意:
这个才是要解释的重点!
*/
接口定义:
JsonSerializable {
// 指定需要被序列化成 JSON 的数据(指定传递给 json_encode($value) 的$value内容)
abstract public mixed jsonSerialize ( void )
}
解释下这个接口存在的意义:
默认情况下,json_encode()一个对象,会将对象的所有属性,编码为一个json对象。例如:
class prev {
$name = 'dongxuemin';
$age = 30;
function a(){
}
...
}
json_encode(new prev()); // 输出 "{'name': 'dongxuemin', 'age': 30}"
如果定义一个类,实现了该接口,并定义了方法
class now implements JsonSerializable{
$name = 'dongxuemin';
$age = 30;
public function jsonSerialize(){
return '我才是要编码的数据';
}
...
}
json_encode(new now()); // 输出 "我才是要编码的数据"
以上2个例子,我们很明显就知道区别了。实现了 JsonSerializable 接口的类,json_encode()时,会去查找 'jsonSerialize()' 方法,有的话,会将返回的内容,作为json_encode()的输入,而不是之前默认的将对象的属性作为json_encode()的输入
laravel的数据库对象就使用了它(好多优秀的框架,应该都实现了它),toJson()方法就是
参考文章:
http://www.laruence.com/2011/10/10/2204.html(PHP国内第一人)
https://segmentfault.com/a/1190000010449725