ホームページ >バックエンド開発 >PHPチュートリアル >PHP json_encode の使用分析手順_PHP チュートリアル

PHP json_encode の使用分析手順_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-13 17:07:311269ブラウズ

この記事では、json_encode の使用状況分析について紹介します。php ソース コードを理解することに興味がある友人は、それを参照してみてください。

json の利点については話しません

私には習慣があり、json を出力するときに sprintf を使用して json 形式に変換するのが好きです。

2 日前に友人が、これは標準ではないので、標準の json 形式を生成するには json_encode を使用する必要があると言いました。もちろん、私はとても落ち込んでいます。

何年も使ってきたので、これが標準ではないことに気づきました。私は標準ではないので、上記は標準のjson形式ですか?

コードは次のとおりですコードをコピー
{a : 'abc'} {'a' : 'abc'} {a : "abc"} {"a" : "abc"}

4 番目のタイプだけが標準の json 形式であることは誰もが知っています。

私はこれをします

コードは次のとおりですコードをコピー
$ret_json='{"%s":"%s"}';

echo json_encode($ret_json,"a","abc");

規格も満たしている必要があります。

この場合、さらに深く尋ねる必要があります。json_encode によって生成される json 形式の違いは何ですか?

アップコード

コードは次のとおりですコードをコピー静的PHP_FUNCTION(json_encode)

JSON_G(error_code) = PHP_JSON_ERROR_NONE;
これは定義された json エラーです。このエラーは json_last_error 関数を使用して取得できます。とにかく使ったことがないんです。
php_json_encode がメインの操作です

{
zval *パラメータ;
smart_str buf = {0};
長いオプション = 0;

If (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", ¶meter, &options) == FAILURE) {
戻る;
                                                                          
JSON_G(error_code) = PHP_JSON_ERROR_NONE;

php_json_encode(&buf, パラメーター, オプション TSRMLS_CC);

ZVAL_STRINGL(return_value, buf.c, buf.len, 1);

smart_str_free(&buf);
}

コードは次のとおりです コードをコピー

PHP_JSON_API void php_json_encode(smart_str *buf, zval *val, int options TSRMLS_DC) /* {{{ */
{
スイッチ(Z_TYPE_P(val))
{
ケース IS_NULL:
smart_str_appendl(buf、 "null"、4);                                                                                                                         
ケース IS_BOOL:
If (Z_BVAL_P(val)) {
outut out true
} else {
SMART_STR_APPENDL(BUF、false "、5);                                                                                                                                                                                                                                              
ケース IS_LONG:
Smart_Str_append_long (buf, z_lval_p (val)) // ロング整形の値を出力します
壊す;
ケース IS_DOUBLE:
                                                                                                                                                                                                                                                                                                                                  イントレン;
                                                                                                                                                                                                     
If (!zend_isinf(dbl) && !zend_isnan(dbl)) {//無限ではない
; SMART_STR_APPENDL(BUF、D、LEN); efree(d);
                                } その他 {
                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "double %.9g は JSON 仕様に準拠していません。0 としてエンコードされています", dbl);
                                        Smart_str_appendc(buf, '0');
                                }
                       }
                        休憩;
 
                case IS_STRING://文字串
                        json_escape_string(buf, Z_STRVAL_P(val), Z_STRLEN_P(val), オプション TSRMLS_CC);
                        休憩;
 
                case IS_ARRAY://数組和对オブジェクト
                ケース IS_OBJECT:
                        json_encode_array(buf, &val, options TSRMLS_CC);
                        休憩;
 
                デフォルト:
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "型はサポートされていないため、null としてエンコードされています");
                        Smart_str_appendl(buf, "null", 4);
                        休憩;
        }
 
        戻ります;
}

明らかに、さまざまなタイプに応じて対応するケースがあります。
最も複雑な型は文字列、配列、オブジェクトです。配列とオブジェクトは同じ操作です。
まず文字列を見てみましょう。文字列は非常に長く、コメントはコード内に直接書き込まれています。

コードは次のとおりです コードをコピー
/options は、次の定数で構成されるバイナリ マスクであるバージョン 5.3 以降でのみサポートされる必要があります: JSON_HEX_QUOT、JSON_HEX_TAG、JSON_HEX_AMP、JSON_HEX_APOS、JSON_NUMERIC_CHECK、JSON_PRETTY_PRINT、JSON_UNESCAPED_SLASHES、JSON_FORCE_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;

If (len == 0) {//長さが 0 の場合、二重引用符 ""
が直接返されます Smart_str_appendl(buf, """", 2);
戻る;
}

If (options & PHP_JSON_NUMERIC_CHECK) {//0 から 9 までの数値かどうかを確認し、数値の場合はデータをlong 型または 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)) {
                                                                                                      int l = spprintf(&tmp, 0, "%.*k", (int) EG(精度), d);
Smart_Str_appendl (buf、tmp、l); efree(tmp);
                                                                                                         php_error_docref(null tsrmls_cc、e_warning、 "double%.9gはjson仕様に準拠していません。 smart_str_appendc(buf、 '0');                                                                                                                                                                                                           戻る; }

}

utf16 = (unsigned short *)safe_emalloc(len, sizeof(unsigned short), 0);
len = utf8_to_utf16(utf16, s, len); //入力した値は一度処理され、1 は 49、a は 97 など、対応する 12 進コードに変換され、utf16 に保存されます。
If (len if (utf16) {
                                                                                                                          }
If (len JSON_G(error_code) = PHP_JSON_ERROR_UTF8;
If (!PG(display_errors)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "引数に無効な UTF-8 シーケンスがあります");
                                                                                                                   smart_str_appendl(buf、 "null"、4);
} else {
smart_str_appendl(buf、 "" ""、2);
}
戻る;
}

smart_str_appendc(buf, '"'); //「
」と入力
//次のコードは、二重引用符、バックスラッシュなどの一部の特殊文字をエスケープします。
while (pos < len)
{
私たち = utf16[pos++];

スイッチ(私たち)
{
ケース '"':
If (オプション & PHP_JSON_HEX_QUOT) {
smart_str_appendl(buf、 "u0022"、6);
                                                                                                                                                Smart_str_appendl(buf, """, 2);
                                }
                                休憩;
 
                        ケース '':
                                Smart_str_appendl(buf, "\", 2);
                                休憩;
ケース '/':
                                Smart_str_appendl(buf, "/", 2);
                                休憩;
 
                        ケース「b」:
                                Smart_str_appendl(buf, "b", 2);
                                休憩;
 
                        ケース「f」:
                                Smart_str_appendl(buf, "f", 2);
                                休憩;
 
                        ケース「n」:
                                Smart_str_appendl(buf, "n", 2);
                                休憩;
 
                        ケース「r」:
                                Smart_str_appendl(buf, "r", 2);
                                休憩;
 
                        ケース「t」:
                                Smart_str_appendl(buf, "t", 2);
                                休憩;
 
                        ケース「<」:
                                if (オプション & PHP_JSON_HEX_TAG) {
                                        Smart_str_appendl(buf, "u003C", 6);
                                } その他 {
                                        Smart_str_appendc(buf, '<');
                                }
                                休憩;
 
                        ケース「>」:
                                if (オプション & PHP_JSON_HEX_TAG) {
                                        Smart_str_appendl(buf, "u003E", 6);
                                } その他 {
                                        Smart_str_appendc(buf, '>');
}
                                休憩;
 
                        ケース「&」:
                                if (オプション & PHP_JSON_HEX_AMP) {
                                        Smart_str_appendl(buf, "u0026", 6);
                                } その他 {
                                        Smart_str_appendc(buf, '&');
                                }
                                休憩;
 
                        ケース「」:
                                if (オプション & PHP_JSON_HEX_APOS) {
SMART_STR_APPENDL(BUF、 "U0027"、6);                                                                                                          smart_str_appendc(buf、 '' ');
                                                                                        休憩

default: //ここまで特殊文字がなければbuf
に値が追加されます If (us >= ' ' && (us & 127) == us) {
smart_str_appendc(buf、(unsigned char)us);
                                                                                                         Smart_str_appendl(buf、 "u"、2);                                                                                                                                                              
smart_str_appendc(buf、digits [us&((1&lt;&lt; 4)-1)]);
を通して smart_str_appendc(buf、digits [us&((1&lt;&lt; 4)-1)]);
を通して smart_str_appendc(buf、digits [us&((1&lt;&lt; 4)-1)]);
を通して smart_str_appendc(buf、digits [us&((1&lt;&lt; 4)-1)]);
                                                                                       休憩
}
}
Smart_str_appendc(buf, '"'); //二重引用符で終了
efree(utf16);
}

配列とオブジェクトを見てみましょう。これも非常に簡単です。

代码如下 复制幣
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);
        } その他 {
                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, '[');
        } その他 {
                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(*データ);
                                if (tmp_ht) {
                                        tmp_ht->nApplyCount++;
                                }
 
                                if (r == PHP_JSON_OUTPUT_ARRAY) {
                                        if (need_comma) {
                                                Smart_str_appendc(buf, ',');
                                        } その他 {
                                                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, ',');
                                                } その他 {
                                                        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);
                                        } その他 {
                                                if (need_comma) {
                                                        Smart_str_appendc(buf, ',');
                                                } その他 {
                                                        need_comma = 1;
                                                }
 
                                                Smart_str_appendc(buf, '"');
                                                Smart_str_append_long(buf, (long) インデックス);
                                                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, ']');
        } その他 {
                Smart_str_appendc(buf, '}');
        }
}

简单分析を通じて、一つの問題を明らかにし、私の上で sprintf を使用する方法は、これは 1 つです、都は拼字文字列です、

さらにパフォーマンスのために、さらに应该鼓動用sprintf来拼接json格式、

json_encode は非常に多くの循環操作を実行するため、消費されるパフォーマンスは線形の O(n^2) です。

http://www.bkjia.com/PHPjc/629905.html

tru​​ehttp://www.bkjia.com/PHPjc/629905.html技術記事この文章では、大手メディア json_encode を使用して分析を行っており、php ソースコードの友人が参考にすることができます。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。