目次
JSON エンコード
中国語処理
その他のパラメータ
オブジェクトと形式の処理
オブジェクト エンコード属性の問題
JSON 解码
错误处理
JSON 序列化接口
总结
ホームページ バックエンド開発 PHPチュートリアル PHP の JSON 関連関数について話しましょう

PHP の JSON 関連関数について話しましょう

Sep 07, 2021 pm 07:41 PM
json関数 php

PHP で JSON を操作するにはどうすればよいですか?この記事では、PHP の JSON 関連関数について詳しく説明し、その関数を使用する際の注意点をいくつか紹介します。

PHP の JSON 関連関数について話しましょう

#私たちが取り組み始めた時代はまだ XML が主流でしたが、今では JSON データ形式がさまざまなアプリケーションでの送信のデファクトスタンダードになりました。 。近年プログラミングと開発を学び始めた学生は、データ送信に XML を使用することに一度も触れたことがないかもしれません。もちろん、時代は常に進歩しており、JSON は XML よりも便利で、高速で、読みやすくなっています。しかし実際には、意味論的な観点から見ると、XML の方が表現力が豊かです。

あまり言う必要はありませんが、PHP での JSON の操作は実際には非常に簡単で、最もよく使用される 2 つの関数は json_encode() と json_decode() です。彼らには気をつけるべきことがいくつかあり、楽しむべきこともいくつかあります。今日はそれを徹底的に勉強してみましょう。

JSON エンコード

まず、後続のエンコード操作のための配列を準備します。

$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;,
        ],
    ],
];
ログイン後にコピー

非常に単純な配列です。実際には特別なことは何もありません。データのネストといくつかの中国語記号と特殊記号があるだけです。通常の 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 番目のパラメーターもあります。たとえば、上記のデータは 3 つのレベルを持つ多次元配列であるため、通常に解析するには少なくとも 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 の最大の用途はデータ送信であり、メソッドはデータ送信には実質的な影響を与えません。プロパティもカプセル化によって異なりますが、パブリックプロパティ、つまりパブリックプロパティのみがエンコードされます。

$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

作者:硬核项目经理

推奨学習: 「PHP ビデオ チュートリアル

以上がPHP の JSON 関連関数について話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Dec 24, 2024 pm 04:42 PM

PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

今まで知らなかったことを後悔している 7 つの PHP 関数 今まで知らなかったことを後悔している 7 つの PHP 関数 Nov 13, 2024 am 09:42 AM

あなたが経験豊富な PHP 開発者であれば、すでにそこにいて、すでにそれを行っていると感じているかもしれません。あなたは、運用を達成するために、かなりの数のアプリケーションを開発し、数百万行のコードをデバッグし、大量のスクリプトを微調整してきました。

PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 Dec 20, 2024 am 11:31 AM

Visual Studio Code (VS Code とも呼ばれる) は、すべての主要なオペレーティング システムで利用できる無料のソース コード エディター (統合開発環境 (IDE)) です。 多くのプログラミング言語の拡張機能の大規模なコレクションを備えた VS Code は、

JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 Apr 05, 2025 am 12:04 AM

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

PHPでHTML/XMLを解析および処理するにはどうすればよいですか? PHPでHTML/XMLを解析および処理するにはどうすればよいですか? Feb 07, 2025 am 11:57 AM

このチュートリアルでは、PHPを使用してXMLドキュメントを効率的に処理する方法を示しています。 XML(拡張可能なマークアップ言語)は、人間の読みやすさとマシン解析の両方に合わせて設計された多用途のテキストベースのマークアップ言語です。一般的にデータストレージに使用されます

母音を文字列にカウントするPHPプログラム 母音を文字列にカウントするPHPプログラム Feb 07, 2025 pm 12:12 PM

文字列は、文字、数字、シンボルを含む一連の文字です。このチュートリアルでは、さまざまな方法を使用してPHPの特定の文字列内の母音の数を計算する方法を学びます。英語の母音は、a、e、i、o、u、そしてそれらは大文字または小文字である可能性があります。 母音とは何ですか? 母音は、特定の発音を表すアルファベットのある文字です。大文字と小文字など、英語には5つの母音があります。 a、e、i、o、u 例1 入力:string = "tutorialspoint" 出力:6 説明する 文字列「TutorialSpoint」の母音は、u、o、i、a、o、iです。合計で6元があります

PHPでの後期静的結合を説明します(静的::)。 PHPでの後期静的結合を説明します(静的::)。 Apr 03, 2025 am 12:04 AM

静的結合(静的::) PHPで後期静的結合(LSB)を実装し、クラスを定義するのではなく、静的コンテキストで呼び出しクラスを参照できるようにします。 1)解析プロセスは実行時に実行されます。2)継承関係のコールクラスを検索します。3)パフォーマンスオーバーヘッドをもたらす可能性があります。

PHPマジックメソッド(__construct、__destruct、__call、__get、__setなど)とは何ですか? PHPマジックメソッド(__construct、__destruct、__call、__get、__setなど)とは何ですか? Apr 03, 2025 am 12:03 AM

PHPの魔法の方法は何ですか? PHPの魔法の方法には次のものが含まれます。1。\ _ \ _コンストラクト、オブジェクトの初期化に使用されます。 2。\ _ \ _リソースのクリーンアップに使用される破壊。 3。\ _ \ _呼び出し、存在しないメソッド呼び出しを処理します。 4。\ _ \ _ get、dynamic属性アクセスを実装します。 5。\ _ \ _セット、動的属性設定を実装します。これらの方法は、特定の状況で自動的に呼び出され、コードの柔軟性と効率を向上させます。

See all articles