Heim  >  Artikel  >  Backend-Entwicklung  >  Lassen Sie uns über JSON-bezogene Funktionen in PHP sprechen

Lassen Sie uns über JSON-bezogene Funktionen in PHP sprechen

青灯夜游
青灯夜游nach vorne
2021-09-07 19:41:533235Durchsuche

Wie betreibe ich JSON in PHP? In diesem Artikel erfahren Sie mehr über JSON-bezogene Funktionen in PHP und stellen einige Dinge vor, auf die Sie bei der Verwendung dieser Funktionen achten müssen. Ich hoffe, er wird Ihnen hilfreich sein!

Lassen Sie uns über JSON-bezogene Funktionen in PHP sprechen

In der Zeit, als wir anfingen zu arbeiten, war die Welt noch von XML dominiert, doch mittlerweile ist das JSON-Datenformat zum De-facto-Standard für die Übertragung in verschiedenen Anwendungen geworden. Studenten, die in den letzten Jahren mit dem Programmieren und Entwickeln begonnen haben, waren möglicherweise noch nie mit der Verwendung von XML zur Datenübertragung vertraut. Natürlich verbessern sich die Zeiten ständig. Im Vergleich zu XML ist JSON komfortabler, schneller und besser lesbar. Tatsächlich ist XML aus semantischer Sicht jedoch ausdrucksstärker.

Ohne weitere Umschweife ist die Bedienung von JSON in PHP eigentlich sehr einfach. Die beiden am häufigsten verwendeten Funktionen sind json_encode() und json_decode(). Es gibt einige Dinge, auf die man achten muss, und einige Dinge, die man genießen kann. Lassen Sie uns es heute eingehend studieren.

JSON-Codierung

Zunächst bereiten wir ein Array für unsere nachfolgenden Codierungsvorgänge vor.

$data = [
    'id' => 1,
    'name' => '测试情况',
    'cat' => [
        '学生 & "在职"',
    ],
    'number' => "123123123",
    'edu' => [
        [
            &#39;name&#39; => &#39;<b>中学</b>&#39;,
            &#39;date&#39; => &#39;2015-2018&#39;,
        ],
        [
            &#39;name&#39; => &#39;<b>大学</b>&#39;,
            &#39;date&#39; => &#39;2018-2022&#39;,
        ],
    ],
];

Ein sehr einfaches Array. Es gibt nur eine Verschachtelung von Daten und einige chinesische und spezielle Symbole. Für die normale JSON-Codierung verwenden Sie einfach json_encode() direkt.

$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"}]}"

Chinesische Verarbeitung

Haben Sie Probleme mit den oben codierten JSON-Daten festgestellt? Das ist richtig, ich glaube, viele Leute werden auf einen Blick erkennen, dass alle chinesischen Schriftzeichen in das uxxxx-Format konvertiert wurden. Dies ist eigentlich die Standardeinstellung. Die Funktion json_encode() konvertiert diese Multibyte-Zeichen in Inhalte im Unicode-Format. Wir können dieses Problem lösen, indem wir direkt nach json_encode () einen konstanten Parameter hinzufügen, sodass chinesische Zeichen normal angezeigt werden können.

$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"}]}"

Natürlich wäre es einfach so langweilig. Denn ein Interviewer hat mich einmal während eines Interviews gefragt, ob ich dieses Problem lösen könnte, ohne diesen konstanten Parameter zu verwenden. Können Sie bitte aufhören, sich den folgenden Code anzusehen, und über Ihre eigenen Lösungen nachdenken?

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"}]}"

ist eigentlich eine sehr einfache Lösung: Konvertieren Sie alle Feldinhalte in den Daten rekursiv in die urlencode()-Codierung, verwenden Sie dann json_encode() zum Codieren und verwenden Sie nach Abschluss urldecode() zum Decodieren. Ist es nicht interessant? Tatsächlich ist dies ein kleiner Trick vieler alter Programmierer, da die JSON_UNESCAPED_UNICODE-Konstante erst nach PHP5.4 verfügbar war. Wenn Sie zuvor wollten, dass die codierten Daten Chinesisch direkt anzeigen, konnten Sie dies nur auf diese Weise tun.

Natürlich ist jetzt die PHP8-Ära und es besteht keine Notwendigkeit für solch mühsame Vorgänge. Es kann jedoch nicht ausgeschlossen werden, dass einige Interviewhallen solche Fragen absichtlich stellen, weil sie erfahrene Programmierer sind. Es reicht aus, dass jeder versteht, dass dies der Fall ist. Schließlich gibt es in der tatsächlichen Projektentwicklung möglicherweise nur sehr wenige Systeme, die Versionen unter PHP5.4 verwenden (es ist in Ordnung, sich nicht an ein solches Unternehmen zu wenden, da Technologieaktualisierungen zu langsam sind). .

Andere Parameter

Zusätzlich zu JSON_UNESCAPED_UNICODE haben wir auch viele konstante Parameter, die verwendet werden können, und dieser Parameter kann parallel betrieben werden, dh mehrere konstante Parameter können gemeinsam wirksam werden.

$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"}]}"

Diese Reihe von Parametern gilt eigentlich für einige spezielle Symbole in unseren Daten, wie z. B. &-Zeichen, a8093152e673feb7aba1828c43532094 HTML-Tags usw. Natürlich gibt es immer noch einige konstante Parameter, die nicht vollständig angezeigt werden. Sie können die Anweisungen im offiziellen Handbuch selbst überprüfen.

Darüber hinaus verfügt json_encode() über einen dritten Parameter, der die Iterationsebene darstellt. Die Daten, die wir oben haben, sind beispielsweise ein mehrdimensionales Array mit drei Ebenen, daher müssen wir ihm mindestens 3 geben, um es normal zu analysieren. Im folgenden Code haben wir nur eine 1 angegeben, sodass der zurückgegebene Inhalt falsch ist. Das heißt, die Kodierung kann nicht erfolgreich sein. Standardmäßig beträgt der Wert dieses Parameters 512.

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

Objekt- und Formatverarbeitung

Standardmäßig kodiert json_encode() entsprechend dem Datentyp. Wenn es sich also um ein Array handelt, ist der kodierte Inhalt das Array-Format von JSON. Zu diesem Zeitpunkt können wir dies auch tun Fügen Sie ein JSON_FORCE_OBJECT hinzu, das ein Array als Objekt codiert.

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

Als wir über mathematikbezogene Funktionen sprachen, haben wir bereits gelernt, dass json_encode() diese nicht codieren kann, wenn die Daten Daten wie NAN enthalten. Tatsächlich können wir einen JSON_PARTIAL_OUTPUT_ON_ERROR hinzufügen, um einige nicht codierbare Werte zu ersetzen. Im folgenden Code können wir damit NAN durch 0 ersetzen.

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

Eigenschaftsprobleme bei der Objektkodierung

Bei Objekten ist der Inhalt nach der JSON-Kodierung derselbe wie bei der Serialisierung. Er enthält nur die Eigenschaften des Objekts, aber keine Methoden. Schließlich wird JSON hauptsächlich für die Datenübertragung verwendet, und die Methoden haben keinen praktischen Einfluss auf die Datenübertragung. Die Eigenschaften unterscheiden sich auch entsprechend ihrer Kapselung. Es werden nur öffentliche Eigenschaften, also öffentliche Eigenschaften, kodiert.

$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(&#39;{"a":1321231231231231231231231231231231231231231231231231231231231231231231233}&#39;, true));
// array(1) {
//     ["a"]=>
//     float(1.3212312312312E+72)
//   }

var_dump(json_decode(&#39;{"a":1321231231231231231231231231231231231231231231231231231231231231231231233}&#39;, 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(&#39;&#39;, 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(&#39;a&#39; => 1, &#39;b&#39; => 3, &#39;c&#39; => 4))) . "\n";
print "Int -> " . json_encode(new jsontest(5)) . "\n";
print "String -> " . json_encode(new jsontest(&#39;Hello, World!&#39;)) . "\n";
print "Object -> " . json_encode(new jsontest((object) array(&#39;a&#39; => 1, &#39;b&#39; => 3, &#39;c&#39; => 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 = [&#39;学生&#39;];
        }
        if (!$edu) {
            $this->edu = new stdClass;
        }
        $this->number = &#39;学号:&#39; . (!$number ? mt_rand() : $number);
        if ($this->id == 2) {
            return [
                $this->id,
                $this->name,
                $this->cat,
                $this->number,
                $this->edu,
            ];
        }
        return [
            &#39;id&#39; => $this->id,
            &#39;name&#39; => $this->name,
            &#39;cat&#39; => $this->cat,
            &#39;number&#39; => $this->number,
            &#39;edu&#39; => $this->edu,
        ];
    }
}

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

var_dump(json_encode([new Student(1, &#39;测试一&#39;), new Student(2, &#39;测试二&#39;)], 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

作者:硬核项目经理

Empfohlenes Lernen: „PHP-Video-Tutorial

Das obige ist der detaillierte Inhalt vonLassen Sie uns über JSON-bezogene Funktionen in PHP sprechen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen