- static PHP_FUNCTION(json_encode)
- {
- zval *parameter;
- long options = 0;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC) |l"、&パラメータ、 &options) == FAILURE) {
- return;
- }
-
- JSON_G(error_code) = PHP_JSON_ERROR_NONE;
-
- php_json_encode(&buf, パラメータ, オプション
-
- ZVAL_STRINGL(return_value, buf.c);バフレン、1);
-
- smart_str_free(&buf);
- }
-
-
コードをコピー
JSON_G(error_code) = PHP_JSON_ERROR_NONE;
これは定義された json エラーです。このエラーは json_last_error 関数を使用して取得できます。とにかく使ったことがないんです。
php_json_encode がメインの操作です
PHP_JSON_API void php_json_encode(smart_str *buf, zval *val, int options TSRMLS_DC) /* {{{ */ - {
- switch (Z_TYPE_P(val))
- {
- case IS_NULL:
- Smart_str_app終了 l(buf , "null", 4); // NULL を出力
-
- case IS_BOOL:
- if (Z_BVAL_P(val)) {
- Smart_str_appendl(buf, "true", 4) // true を出力 } else {
- Smart_str_appendl (buf, "false", 5);// false を出力します
- }
- Break;
-
- case IS_LONG:
- Smart_str_append_long(buf, Z_LVAL_P(val));// 長整数の値を出力します
-
- case; IS_DOUBLE:
- { char *d = NULL;
- int len;
- double dbl = Z_DVAL_P(val)
-
- if (!zend_isinf(dbl) && !zend_isnan(dbl)) {//非無限
- len = spprintf (&d , 0, "%.*k", (int) EG(精度), dbl);
- Smart_str_appendl(buf, d, len)
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING) , " double %.9g は JSON 仕様に準拠していません。0 としてエンコードされます", dbl);
- Smart_str_appendc(buf, '0');
-
- case IS_STRING://string
- json_escape_string( buf , Z_STRVAL_P(val), Z_STRLEN_P(val), オプション TSRMLS_CC);
-
- case IS_ARRAY://配列とオブジェクト
- case IS_OBJECT:
- json_encode_array(buf, &val, options TSRMLS_CC);
- デフォルト:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "タイプはサポートされていません。null としてエンコードされています");
-
- }
-
- return;
-
-
明らかに、さまざまなタイプに応じて対応するケースがあります。
最も複雑な型は文字列、配列、オブジェクトです。配列とオブジェクトは同じ操作です。
まず文字列を見てみましょう。文字列は非常に長く、コメントはコード内に直接書き込まれています。
-
- //オプションは、次の定数で構成されるバイナリ マスクであるバージョン 5.3 以降でのみサポートされる必要があります: JSON_HEX_QUOT、JSON_HEX_TAG、JSON_HEX_AMP、JSON_HEX_APOS、JSON_NUMERIC_CHECK、JSON_PRETTY_PRINT、JSON_UNESCAPED_SLASHES、 OBJECT、JSON_UNESCAPED_UNICODEは使用していませんが。 。 。 。
- static void json_escape_string(smart_str *buf, char *s, int len, int options TSRMLS_DC) /* {{{ */
- int pos = 0;
- unsigned short *utf16; len == 0) {//長さが 0 の場合、二重引用符 "" を直接返します
- Smart_str_appendl(buf, """", 2)
- return;
- }
-
- if (options & PHP_JSON_NUMERIC_CHECK) {//検出0 から 9 までの数値ですか? 数値の場合、データはlong 型または double 型として直接返されます。
- double d;
- int 型;
-
- if ((type = is_numeric_string(s, len, &p, &d, 0)) != 0) {
- if (type == IS_LONG) {
- Smart_str_append_long(buf) , p);
- } else if (type == IS_DOUBLE) {
- if (!zend_isinf(d) && !zend_isnan(d)) {
- char *tmp;
- int l = spprintf(&tmp, 0, "%.* k", (int) EG(precision), d);
- Smart_str_appendl(buf, tmp, l);
- efree(tmp);
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "double %.9g は準拠していません) 0", d); としてエンコードされた JSON 仕様に変換します。
- Smart_str_appendc(buf, '0');
- }
- }
- return;
- }
-
- }
-
- utf16 = (unsigned short *)safe_emalloc(len, sizeof( unsigned short), 0);
- len = utf8_to_utf16(utf16, s, len); //入力した値は 1 回処理され、対応する Dec コードに変換されます。たとえば、1 は 49、a は 97 です。 utf16に。
- if (len if (utf16) {
- efree(utf16);
- }
- if (len JSON_G(error_code) = PHP_JSON_ERROR_UTF8;
- if (!PG(display_errors)) {
- php_error_docref(NULL TSRMLS_CC, E_WARN)イング、」引数に無効な UTF-8 シーケンスがあります");
- }
- smart_str_appendl(buf, "null", 4);
- } else {
- smart_str_appendl(buf, """", 2);
- }
- return;
- }
-
- Smart_str_appendc(buf, '"'); //「」と入力します
-
- //次のコードは、二重引用符、バックスラッシュなどの一部の特殊文字をエスケープするものです。
- while (pos < len)
- {
- us = utf16[ pos++];
-
- switch (us)
- {
- case '"':
- if (options & PHP_JSON_HEX_QUOT) {
- Smart_str_appendl(buf, "\u0022", 6);
- } else {
- Smart_str_appendl(buf, " \" ", 2);
- }
- ブレーク;
-
- case '\':
- Smart_str_appendl(buf, "\\", 2);
- ブレーク;
- case '/':
- Smart_str_appendl(buf, "\/" , 2 );
-
- ケース 'b':
-
- ケース 'f':
- ブレーク;
-
- ケース 'n':
- smart_str_appendl(buf, "\n", 2);
-
- ケース 'r':
-
- ケース; 't':
- smart_str_appendl(buf, "\t", 2);
- break;
-
- case '<':
- if (options & PHP_JSON_HEX_TAG) {
- smart_str_appendl(buf, "\u003C", 6) ; } else {
- Smart_str_appendc(buf, '<');
-
- case '>':
- if (options & PHP_JSON_HEX_TAG) {
- Smart_str_appendl(buf, "\u003E", 6); else {
- Smart_str_appendc(buf, '>');
-
- case '&':
- if (options & PHP_JSON_HEX_AMP) {
- Smart_str_appendl(buf, "\u0026", 6);
- smart_str_appendc(buf, '&');
- }
-
- case '':
- if (options & PHP_JSON_HEX_APOS) {
- Smart_str_appendl(buf, "\u0027", 6); _appendc( buf, '');
- }
- Break;
-
- デフォルト: //ここまでは、特殊文字なしで buf に追加されます
- if (us >= ' ' && (us & 127) == us ) {
- smart_str_appendc(buf, (unsigned char) us
- }else {
- smart_str_appendl(buf, "\u", 2);
- us = REVERSE16(us);
-
- smart_str_appendc(buf, 数字[us & ((1 << 4) - 1)]);
- 私たち >>= 4;
- smart_str_appendc(buf, 数字[us & ((1 << 4) - 1)]);
- 私たち >>= 4;
- smart_str_appendc(buf, 数字[us & ((1 << 4) - 1)]);
- 私たち >>= 4;
- smart_str_appendc(buf, 数字[us & ((1 << 4) - 1)]);
- }
- 休憩;
- }
- }
- Smart_str_appendc(buf, '"'); // 双引号を終了。
配列とオブジェクトを見てみましょう。これも非常に簡単です。
- static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC) /* {{{ */
- {
- int i, r;
- ハッシュテーブル *myht;
-
- if (Z_TYPE_PP(val) == IS_ARRAY) {
- myht = HASH_OF(*val);
- r = (オプション & PHP_JSON_FORCE_OBJECT) ? PHP_JSON_OUTPUT_OBJECT : json_determine_array_type(val TSRMLS_CC);
- } else {
- myht = Z_OBJPROP_PP(val);
- r = PHP_JSON_OUTPUT_OBJECT;
- }
-
- if (myht && myht->nApplyCount > 1) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "再帰が検出されました");
- smart_str_appendl(buf, "null", 4);
- 戻る;
- }
- //开始标签
- if (r == PHP_JSON_OUTPUT_ARRAY) {
- Smart_str_appendc(buf, '[');
- } else {
- Smart_str_appendc(buf, '{');
- }
-
- i = myht ? zend_hash_num_elements(myht) : 0;
-
- if (i > 0)
- {
- char *key;
- zval **データ;
- ulong インデックス;
- uint key_len;
- ハッシュ位置の位置;
- ハッシュテーブル *tmp_ht;
- int need_comma = 0;
-
- zend_hash_internal_pointer_reset_ex(myht, &pos);
- //便利哈希表
- for (;; zend_hash_move_forward_ex(myht, &pos)) {
- i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
- if (i == HASH_KEY_NON_EXISTANT)
- ブレーク;
-
- if (zend_hash_get_current_data_ex(myht, (void **) &data, &pos) == SUCCESS) {
- tmp_ht = HASH_OF(*data);
- if (tmp_ht) {
- tmp_ht->nApplyCount++;
- }
-
- if (r == PHP_JSON_OUTPUT_ARRAY) {
- if (need_comma) {
- Smart_str_appendc(buf, ',');
- } else {
- need_comma = 1;
- }
- // buf中に追加します
- php_json_encode(buf, *data, options TSRMLS_CC);
- } else if (r == PHP_JSON_OUTPUT_OBJECT) {
- if (i == HASH_KEY_IS_STRING) {
- if (key[0] == ' ' && Z_TYPE_PP(val) == IS_OBJECT) {
- /* 保護されたメンバーとプライベートメンバーをスキップします。 */
- if (tmp_ht) {
- tmp_ht->nApplyCount--;
- }
- 続けます。
- }
-
- if (need_comma) {
- Smart_str_appendc(buf, ',');
- } else {
- need_comma = 1;
- }
-
- json_escape_string(buf, key, key_len - 1, options & ~PHP_JSON_NUMERIC_CHECK TSRMLS_CC);
- smart_str_appendc(buf, ':');
-
- php_json_encode(buf, *data, options TSRMLS_CC);
- } else {
- if (need_comma) {
- Smart_str_appendc(buf, ',');
- } else {
- need_comma = 1;
- }
-
- smart_str_appendc(buf, '"');
- smart_str_append_long(buf, (long)index);
- smart_str_appendc(buf, '"');
- smart_str_appendc(buf, ':');
-
- php_json_encode(buf, *data, options TSRMLS_CC);
- }
- }
-
- if (tmp_ht) {
- tmp_ht->nApplyCount--;
- }
- }
- }
- }
- //结束标签
- if (r == PHP_JSON_OUTPUT_ARRAY) {
- Smart_str_appendc(buf, ']');
- } else {
- Smart_str_appendc(buf, '}');
- }
- }
复制代コード
通简单分析、证明了一问题、跟我上面用sprintf的方法其实是一样的,都是拼接字串,
さらにパフォーマンスのために、さらに应该鼓動用sprintf来拼接json格式、
json_encode は非常に多くの循環操作を実行するため、消費されるパフォーマンスは線性の O(n) です。
|