この記事では、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 形式の違いは何ですか?
アップコード
コードをコピー | |||||||||||||
{ 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) /* {{{ */ |
明らかに、さまざまなタイプに応じて対応するケースがあります。
最も複雑な型は文字列、配列、オブジェクトです。配列とオブジェクトは同じ操作です。
まず文字列を見てみましょう。文字列は非常に長く、コメントはコード内に直接書き込まれています。
コードは次のとおりです | コードをコピー |
/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