PHP学习_聊聊PHP中与JSON相关的函数

2021-09-09 0 996 百度已收录

PHP中要怎样操纵JSON?本篇文章带大师深化进修一下PHP中与JSON相关的函数,介绍一下运用这些函数需求留意的一些中央,但愿对于大师有所协助!

PHP学习_聊聊PHP中与JSON相关的函数

正在咱们昔时方才下班的阿谁年月,还满是 XML 的全国,但如今 JSON 数据格局曾经是各类使用传输的现实规范了。近年开端进修编程开辟的同窗能够都完整不打仗过运用 XML 来停止数据传输。固然,期间是不断正在提高的,JSON 比拟 XML 来讲,愈加中央便快速,可读性更高。但实在从语义的角度来讲,XML 的施展阐发方式更强。

话未几说,正在 PHP 中操纵 JSON 实在十分复杂,大师最经常使用的不过也便是 json_encode() 以及 json_decode() 这两个函数。它们有一些需求留意之处,也有一些好玩之处。明天,咱们就来深化地再进修一下。

JSON 编码

起首,咱们预备一个数组,用于咱们前面编码的操纵。

$data = [
    'id' => 1,
    'name' => '测试状况',
    'cat' => [
        '先生 & "退职"',
    ],
    'number' => "123123123",
    'edu' => [
        [
            'name' => '<b>中学</b>',
            'date' => '2015-2018',
        ],
        [
            'name' => '<b>年夜学</b>',
            'date' => '2018-2022',
        ],
    ],
];

十分复杂地数组,实在也不甚么出格的工具,只是无数据的嵌套,有一些中文以及非凡标记罢了。关于平凡的 JSON 编码来讲,间接运用 json_encode() 就能够了。

$json1 = json_encode($data);
var_dump($json1);
// string(215) "{"id":1,"name":"\\u6d4b\\u8bd5\\u60c5\\u51b5","cat":["\\u5b66\\u751f & \\"\\u5728\\u804c\\""],"number":"123123123","edu":[{"name":"<b>\\u4e2d\\u5b66<\\/b>","date":"2015-2018"},{"name":"<b>\\u5927\\u5b66<\\/b>","date":"2018-2022"}]}"

中文处置

下面编码后的 JSON 数据发明了甚么成绩没?没错,置信很多人一眼就会看出,中笔墨符全被转换成为了 \\uxxxx 这类格局。这实际上是正在默许状况下,json_encode() 函数城市将这些多字节字符转换成 Unicode 格局的内容。咱们间接正在 json_encode() 前面添加一个常量参数就能够处理这个成绩,让中笔墨符一般地表现进去。

$json1 = json_encode($data, JSON_UNESCAPED_UNICODE);
var_dump($json1);
// string(179) "{"id":1,"name":"测试状况","cat":["先生 & \\"退职\\""],"number":"123123123","edu":[{"name":"<b>中学<\\/b>","date":"2015-2018"},{"name":"<b>年夜学<\\/b>","date":"2018-2022"}]}"

固然,只是如许就太没意义了。由于我已经正在口试的时分就有一名口试官问过我,假如处理这类成绩,并且不必这个常量参数。大师能够先没有看上面的代码,考虑一下本人有甚么处理计划吗?

function t($data)
{
    foreach ($data as $k => $d) {
        if (is_object($d)) {
            $d = (array) $d;
        }
        if (is_array($d)) {
            $data[$k] = t($d);
        } else {
            $data[$k] = urlencode($d);
        }
    }
    return $data;
}
$newData = t($data);

$json1 = json_encode($newData);
var_dump(urldecode($json1));
// string(177) "{"id":"1","name":"测试状况","cat":["先生 & "退职""],"number":"123123123","edu":[{"name":"<b>中学</b>","date":"2015-2018"},{"name":"<b>年夜学</b>","date":"2018-2022"}]}"

实在便是一个很复杂地处理计划,递归地将数据中一切字段内容转换成 urlencode() 编码,而后再运用 json_encode() 编码,实现以后再运用 urldecode() 反解进去。是否是有点意义?实在这是很多老顺序员的一个小本领,由于 JSON_UNESCAPED_UNICODE 这个常量是正在 PHP5.4 以后才有的,以前的话假如想让编码后的数据间接表现中文,就只能如许操纵了。

固然,如今曾经是 PHP8 期间了,早就曾经没有需求这么费事地操纵了,不外也不克不及扫除有些口试馆仗着本人是老码农成心出些如许的标题。大师理解下,晓得有这么回事就能够了,究竟结果正在实践的名目开辟中,运用 PHP5.4 如下版本的零碎能够还真黑白常少了(如许的公司没有去也罢,技能更新患上太慢了)。

别的参数

除 JSON_UNESCAPED_UNICODE 以外,咱们另有很多的常量参数可使用,并且这个参数是能够并行操纵的,也便是能够多个常量参数配合失效。

$json1 = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_NUMERIC_CHECK | JSON_HEX_QUOT);
var_dump($json1);
// string(230) "{"id":1,"name":"测试状况","cat":["先生 \\u0026 \\u0022退职\\u0022"],"number":123123123,"edu":[{"name":"\\u003Cb\\u003E中学\\u003C\\/b\\u003E","date":"2015-2018"},{"name":"\\u003Cb\\u003E年夜学\\u003C\\/b\\u003E","date":"2018-2022"}]}"

这一堆参数实际上是针对于的咱们数据中的一些非凡标记,比方说 & 符、<> HTML 标签等。固然,另有一些常量参数不局部展现进去,大师能够本人查阅民间手册中的说明。

别的,json_encode() 另有第三个参数,代表的是迭代的层级。比方咱们下面的这个数据是多维数组,它有三层,以是咱们至多要给到 3 才干一般地剖析。上面代码咱们只是给了一个 1 ,以是前往的内容便是 false 。也便是没法编码成功。默许状况下,这个参数的值是 512 。

var_dump(json_encode($data, JSON_UNESCAPED_UNICODE, 1)); // bool(false)

工具合格式处置

默许状况下,json_encode() 会依据数据的范例停止编码,以是假如是数组的话,那末它编码以后的内容便是 JSON 的数组格局,这时候咱们也能够增加一个 JSON_FORCE_OBJECT ,让它将一个数组以工具的方式停止编码。

$data = [];
var_dump(json_encode($data)); // string(2) "[]"
var_dump(json_encode($data, JSON_FORCE_OBJECT)); // string(2) "{}"

以前正在讲数学相关函数的时分咱们进修过,假如数据中有 NAN 这类数据的话,json_encode() 是没法编码的,实在咱们能够增加一个 JSON_PARTIAL_OUTPUT_ON_ERROR ,对于一些不成编码的值停止交换。上面的代码中,咱们就能够运用它让 NAN 交换成 0 。

$data = NAN;
var_dump(json_encode($data)); // bool(false)
var_dump(json_encode($data, JSON_PARTIAL_OUTPUT_ON_ERROR)); // 0

工具编码的属性成绩

关于工具来讲,JSON 编码后的内容就以及序列化同样,只会有工具的属性而没有会无方法。究竟结果 JSON 最年夜的用途便是用于数据传输的,办法关于数据传输来讲不甚么实践的感化。而属性也会依据它的封装状况有所差别,只会编码大众的,也便是 public 的属性。

$data = new class
{
    private $a = 1;
    protected $b = 2;
    public $c = 3;

    public function x(){
        
    }
};
var_dump(json_encode($data)); // string(7) "{"c":3}"

从这段测试代码中能够看出,protected 、 private 属性和阿谁办法都没有会被编码。

JSON 解码

关于 JSON 解码来讲,实在更复杂一些,由于 json_decode() 的常量参数不那末多。

var_dump(json_decode($json1));
// object(stdClass)#1 (5) {
//     ["id"]=>
//     int(1)
//     ["name"]=>
//     string(12) "测试状况"
//     ["cat"]=>
// ……
// ……

var_dump(json_decode($json1, true));
// array(5) {
//     ["id"]=>
//     int(1)
//     ["name"]=>
//     string(12) "测试状况"
//     ["cat"]=>
// ……
// ……

起首仍是看下它的第二个参数。这个参数的感化实在从代码中就能够看进去,假如没有填这个参数,也便是默许状况下它的值是 false ,那末解码进去的数据是工具格局的。而咱们将这具参数配置为 true 的话,那末解码后的后果就会是数组格局的。这个也是大师十分经常使用的功用,就未几做表明了。

var_dump(json_decode('{"a":1321231231231231231231231231231231231231231231231231231231231231231231233}', true));
// array(1) {
//     ["a"]=>
//     float(1.3212312312312E+72)
//   }

var_dump(json_decode('{"a":1321231231231231231231231231231231231231231231231231231231231231231231233}', true, 512, JSON_BIGINT_AS_STRING));
// array(1) {
//     ["a"]=>
//     string(73) "1321231231231231231231231231231231231231231231231231231231231231231231233"
//   }

关于这类十分长的数字格局的数据来讲,假如间接 json_decode() 解码的话,它会间接转换成 迷信计数法 。咱们能够间接运用一个 JSON_BIGINT_AS_STRING 常量参数,将这类数据正在解码的时分间接转换成字符串,实在也便是保存了数据的原始样貌。留意,这里 json_decode() 函数的参数由于有阿谁转换工具为数组的参数存正在,以是它有四个参数,第三个参数是迭代深度,第四个便是界说这些格局化常量值的。并且它以及 json_encode() 是反过去的,迭代深度参数正在前,格局常量参数正在前面,这里必定要留意哦!

假如数据是过错的,那末 json_decode() 会前往 NULL 。

var_dump(json_decode("", true)); // NULL
var_dump(json_decode("{a:1}", true)); // NULL

过错处置

下面两段代码中咱们都演示了假如编码或者解码的数占有成绩会呈现甚么状况,比方 json_encode() 会前往 false ,json_decode() 会前往 NULL 。可是详细的缘由呢?

$data = NAN;
var_dump(json_encode($data)); // bool(false)
var_dump(json_last_error()); // int(7)
var_dump(json_last_error_msg()); // string(34) "Inf and NaN cannot be JSON encoded"

没错,json_last_error() 以及 json_last_error_msg() 便是前往 JSON 操纵时的过错信息的。也便是说,json_encode() 以及 json_decode() 正在一般状况下是没有会报错的,咱们假如要取得过错信息,就患上运用这两个函数来获得。这一点也是很多老手小同窗不留意过之处,没过错信息,没有抛出非常成绩对于咱们的开辟调试实际上是十分没有敌对的。由于极可能找了半天都没有晓得成绩出正在那里。

正在 PHP7.3 以后,新添加了一个常量参数,可让咱们的 json_encode() 以及 json_decode() 正在编解码过错的时分抛出非常,如许咱们就能够疾速地定位成绩了,如今假如大师的零碎运转情况是 PHP7.3 以上的话,十分推选运用这个常量参数让零碎来抛出非常。

// php7.3
var_dump(json_encode($data, JSON_THROW_ON_ERROR));
// Fatal error: Uncaught JsonException: Inf and NaN cannot be JSON encoded

var_dump(json_decode('', true, 512, JSON_THROW_ON_ERROR));
// PHP Fatal error:  Uncaught JsonException: Syntax error

JSON_THROW_ON_ERROR 是对于 json_encode() 以及 json_decode() 都起效的。异样,只需设定了这个常量参数,咱们就能够运用 try...catch 来停止捕捉了。

try {
    var_dump(json_encode($data, JSON_THROW_ON_ERROR));
} catch (JsonException $e) {
    var_dump($e->getMessage()); // string(34) "Inf and NaN cannot be JSON encoded"
}

JSON 序列化接口

正在以前的文章中,咱们进修过 运用Serializable接口来自界说PHP中类的序列化 。也便是说,经过 Serializable 接口咱们能够自界说序列化的格局内容。而关于 JSON 来讲,异样也供给了一个 JsonSerializable 接口来完成我自界说 JSON 编码时的工具格局内容。

class jsontest implements JsonSerializable
{
    public function __construct($value)
    {$this->value = $value;}
    public function jsonSerialize()
    {return $this->value;}
}

print "Null -> " . json_encode(new jsontest(null)) . "\\n";
print "Array -> " . json_encode(new jsontest(array(1, 2, 3))) . "\\n";
print "Assoc. -> " . json_encode(new jsontest(array('a' => 1, 'b' => 3, 'c' => 4))) . "\\n";
print "Int -> " . json_encode(new jsontest(5)) . "\\n";
print "String -> " . json_encode(new jsontest('Hello, World!')) . "\\n";
print "Object -> " . json_encode(new jsontest((object) array('a' => 1, 'b' => 3, 'c' => 4))) . "\\n";
// Null -> null
// Array -> [1,2,3]
// Assoc. -> {"a":1,"b":3,"c":4}
// Int -> 5
// String -> "Hello, World!"
// Object -> {"a":1,"b":3,"c":4}

这是一个小的示例,只要要完成 JsonSerializable 接口中的 jsonSerialize() 办法并前往内容就能够完成这个 jsontest 工具的 JSON 编码格局的指定。这里咱们只是复杂地前往了数据的内容,实在以及平凡的 json_encode() 没甚么太年夜的差别。上面咱们经过一个庞大的例子看一下。

class Student implements JsonSerializable
{
    private $id;
    private $name;
    private $cat;
    private $number;
    private $edu;
    public function __construct($id, $name, $cat = null, $number = null, $edu = null)
    {
        $this->id = $id;
        $this->name = $name;
        $this->cat = $cat;
        $this->number = $number;
        $this->edu = $edu;

    }
    public function jsonSerialize()
    {
        if (!$cat) {
            $this->cat = ['先生'];
        }
        if (!$edu) {
            $this->edu = new stdClass;
        }
        $this->number = '学号:' . (!$number ? mt_rand() : $number);
        if ($this->id == 2) {
            return [
                $this->id,
                $this->name,
                $this->cat,
                $this->number,
                $this->edu,
            ];
        }
        return [
            'id' => $this->id,
            'name' => $this->name,
            'cat' => $this->cat,
            'number' => $this->number,
            'edu' => $this->edu,
        ];
    }
}

var_dump(json_encode(new Student(1, '测试一'), JSON_UNESCAPED_UNICODE));
// string(82) "{"id":1,"name":"测试一","cat":["先生"],"number":"学号:14017495","edu":{}}"

var_dump(json_encode([new Student(1, '测试一'), new Student(2, '测试二')], JSON_UNESCAPED_UNICODE));
// string(137) "[{"id":1,"name":"测试一","cat":["先生"],"number":"学号:1713936069","edu":{}},[2,"测试二",["先生"],"学号:499173036",{}]]"

正在这个例子中,咱们正在 jsonSerialize() 做了一些操纵。假如数据不传值,比方为 null 的状况下就给一个默许值。而后正在 id 为 2 的状况下前往一个平凡数组。大师能够看到最初一段正文中的第二条数据的格局。

这个接口是否是颇有意义,置信大师能够对于下面的 json_encode() 以及 json_decode() 十分熟习了,但这个接口估量很多人真的是没打仗过,是否是十分成心思。

总结

果真,甚么工作都怕深挖。没有学没有晓得,一学吓一跳,往常每天用患上这么复杂的 JSON 操纵的相关函数实在另有良多好用的功用是咱们没有晓得的。固然,最次要的仍是看看文档,弄理解理睬而且记着一些十分好用的常量参数,别的,抛出非常的功用也是这篇文章的重点内容,倡议版本到达的冤家最佳都能运用 JSON_THROW_ON_ERROR 来让过错实时抛出,实时发明哦!

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202012/source/11.深化进修PHP中的JSON相关函数.php

参考文档:

https://www.php.net/manual/zh/book.json.php

本文转载自:https://juejin.cn/post/7001652041814638600

作者:硬核名目司理

推选进修:《PHP视频教程

以上便是聊聊PHP中与JSON相关的函数的具体内容,更多请存眷酷吧易资源网别的相关文章!

 

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

酷吧易资源网 PHP教程 PHP学习_聊聊PHP中与JSON相关的函数 https://www.kubayi.com/7661.html

常见问题

相关文章

评论
暂无评论