ホームページ  >  記事  >  バックエンド開発  >  php json_encodeアプリケーション分析

php json_encodeアプリケーション分析

WBOY
WBOYオリジナル
2016-07-25 09:04:221014ブラウズ
  1. static PHP_FUNCTION(json_encode)
  2. {
  3. zval *parameter;
  4. long options = 0;
  5. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC) |l"、&パラメータ、 &options) == FAILURE) {
  6. return;
  7. }
  8. JSON_G(error_code) = PHP_JSON_ERROR_NONE;
  9. php_json_encode(&buf, パラメータ, オプション
  10. ZVAL_STRINGL(return_value, buf.c);バフレン、1);
  11. smart_str_free(&buf);
  12. }
コードをコピー
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) /* {{{ */
  1. {
  2. switch (Z_TYPE_P(val))
  3. {
  4. case IS_NULL:
  5. Smart_str_app終了 l(buf , "null", 4); // NULL を出力
  6. case IS_BOOL:
  7. if (Z_BVAL_P(val)) {
  8. Smart_str_appendl(buf, "true", 4) // true を出力 } else {
  9. Smart_str_appendl (buf, "false", 5);// false を出力します
  10. }
  11. Break;
  12. case IS_LONG:
  13. Smart_str_append_long(buf, Z_LVAL_P(val));// 長整数の値を出力します
  14. case; IS_DOUBLE:
  15. { char *d = NULL;
  16. int len;
  17. double dbl = Z_DVAL_P(val)
  18. if (!zend_isinf(dbl) && !zend_isnan(dbl)) {//非無限
  19. len = spprintf (&d , 0, "%.*k", (int) EG(精度), dbl);
  20. Smart_str_appendl(buf, d, len)
  21. } else {
  22. php_error_docref(NULL TSRMLS_CC, E_WARNING) , " double %.9g は JSON 仕様に準拠していません。0 としてエンコードされます", dbl);
  23. Smart_str_appendc(buf, '0');
  24. case IS_STRING://string
  25. json_escape_string( buf , Z_STRVAL_P(val), Z_STRLEN_P(val), オプション TSRMLS_CC);
  26. case IS_ARRAY://配列とオブジェクト
  27. case IS_OBJECT:
  28. json_encode_array(buf, &val, options TSRMLS_CC);
  29. デフォルト:
  30. php_error_docref(NULL TSRMLS_CC, E_WARNING, "タイプはサポートされていません。null としてエンコードされています");
  31. }
  32. return;
  33. 明らかに、さまざまなタイプに応じて対応するケースがあります。 最も複雑な型は文字列、配列、オブジェクトです。配列とオブジェクトは同じ操作です。 まず文字列を見てみましょう。文字列は非常に長く、コメントはコード内に直接書き込まれています。

    1. //オプションは、次の定数で構成されるバイナリ マスクであるバージョン 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は使用していませんが。 。 。 。
    2. static void json_escape_string(smart_str *buf, char *s, int len, int options TSRMLS_DC) /* {{{ */
    3. int pos = 0;
    4. unsigned short *utf16; len == 0) {//長さが 0 の場合、二重引用符 "" を直接返します
    5. Smart_str_appendl(buf, """", 2)
    6. return;
    7. }
    8. if (options & PHP_JSON_NUMERIC_CHECK) {//検出0 から 9 までの数値ですか? 数値の場合、データはlong 型または double 型として直接返されます。
    9. double d;
    10. int 型;
    11. if ((type = is_numeric_string(s, len, &p, &d, 0)) != 0) {
    12. if (type == IS_LONG) {
    13. Smart_str_append_long(buf) , p);
    14. } else if (type == IS_DOUBLE) {
    15. if (!zend_isinf(d) && !zend_isnan(d)) {
    16. char *tmp;
    17. int l = spprintf(&tmp, 0, "%.* k", (int) EG(precision), d);
    18. Smart_str_appendl(buf, tmp, l);
    19. efree(tmp);
    20. } else {
    21. php_error_docref(NULL TSRMLS_CC, E_WARNING, "double %.9g は準拠していません) 0", d); としてエンコードされた JSON 仕様に変換します。
    22. Smart_str_appendc(buf, '0');
    23. }
    24. }
    25. return;
    26. }
    27. }
    28. utf16 = (unsigned short *)safe_emalloc(len, sizeof( unsigned short), 0);
    29. len = utf8_to_utf16(utf16, s, len); //入力した値は 1 回処理され、対応する Dec コードに変換されます。たとえば、1 は 49、a は 97 です。 utf16に。
    30. if (len if (utf16) {
    31. efree(utf16);
    32. }
    33. if (len JSON_G(error_code) = PHP_JSON_ERROR_UTF8;
    34. if (!PG(display_errors)) {
    35. php_error_docref(NULL TSRMLS_CC, E_WARN)イング、」引数に無効な UTF-8 シーケンスがあります");
    36. }
    37. smart_str_appendl(buf, "null", 4);
    38. } else {
    39. smart_str_appendl(buf, """", 2);
    40. }
    41. return;
    42. }
    43. Smart_str_appendc(buf, '"'); //「」と入力します
    44. //次のコードは、二重引用符、バックスラッシュなどの一部の特殊文字をエスケープするものです。
    45. while (pos < len)
    46. {
    47. us = utf16[ pos++];
    48. switch (us)
    49. {
    50. case '"':
    51. if (options & PHP_JSON_HEX_QUOT) {
    52. Smart_str_appendl(buf, "\u0022", 6);
    53. } else {
    54. Smart_str_appendl(buf, " \" ", 2);
    55. }
    56. ブレーク;
    57. case '\':
    58. Smart_str_appendl(buf, "\\", 2);
    59. ブレーク;
    60. case '/':
    61. Smart_str_appendl(buf, "\/" , 2 );
    62. ケース 'b':
    63. ケース 'f':
    64. ブレーク;
    65. ケース 'n':
    66. smart_str_appendl(buf, "\n", 2);
    67. ケース 'r':
    68. ケース; 't':
    69. smart_str_appendl(buf, "\t", 2);
    70. break;
    71. case '<':
    72. if (options & PHP_JSON_HEX_TAG) {
    73. smart_str_appendl(buf, "\u003C", 6) ; } else {
    74. Smart_str_appendc(buf, '<');
    75. case '>':
    76. if (options & PHP_JSON_HEX_TAG) {
    77. Smart_str_appendl(buf, "\u003E", 6); else {
    78. Smart_str_appendc(buf, '>');
    79. case '&':
    80. if (options & PHP_JSON_HEX_AMP) {
    81. Smart_str_appendl(buf, "\u0026", 6);
    82. smart_str_appendc(buf, '&');
    83. }
    84. case '':
    85. if (options & PHP_JSON_HEX_APOS) {
    86. Smart_str_appendl(buf, "\u0027", 6); _appendc( buf, '');
    87. }
    88. Break;
    89. デフォルト: //ここまでは、特殊文字なしで buf に追加されます
    90. if (us >= ' ' && (us & 127) == us ) {
    91. smart_str_appendc(buf, (unsigned char) us
    92. }else {
    93. smart_str_appendl(buf, "\u", 2);
    94. us = REVERSE16(us);
    95. smart_str_appendc(buf, 数字[us & ((1 << 4) - 1)]);
    96. 私たち >>= 4;
    97. smart_str_appendc(buf, 数字[us & ((1 << 4) - 1)]);
    98. 私たち >>= 4;
    99. smart_str_appendc(buf, 数字[us & ((1 << 4) - 1)]);
    100. 私たち >>= 4;
    101. smart_str_appendc(buf, 数字[us & ((1 << 4) - 1)]);
    102. }
    103. 休憩;
    104. }
    105. }
    106. Smart_str_appendc(buf, '"'); // 双引号を終了。

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

      1. static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC) /* {{{ */
      2. {
      3. int i, r;
      4. ハッシュテーブル *myht;
      5. if (Z_TYPE_PP(val) == IS_ARRAY) {
      6. myht = HASH_OF(*val);
      7. r = (オプション & PHP_JSON_FORCE_OBJECT) ? PHP_JSON_OUTPUT_OBJECT : json_determine_array_type(val TSRMLS_CC);
      8. } else {
      9. myht = Z_OBJPROP_PP(val);
      10. r = PHP_JSON_OUTPUT_OBJECT;
      11. }
      12. if (myht && myht->nApplyCount > 1) {
      13. php_error_docref(NULL TSRMLS_CC, E_WARNING, "再帰が検出されました");
      14. smart_str_appendl(buf, "null", 4);
      15. 戻る;
      16. }
      17. //开始标签
      18. if (r == PHP_JSON_OUTPUT_ARRAY) {
      19. Smart_str_appendc(buf, '[');
      20. } else {
      21. Smart_str_appendc(buf, '{');
      22. }
      23. i = myht ? zend_hash_num_elements(myht) : 0;
      24. if (i > 0)
      25. {
      26. char *key;
      27. zval **データ;
      28. ulong インデックス;
      29. uint key_len;
      30. ハッシュ位置の位置;
      31. ハッシュテーブル *tmp_ht;
      32. int need_comma = 0;
      33. zend_hash_internal_pointer_reset_ex(myht, &pos);
      34. //便利哈希表
      35. for (;; zend_hash_move_forward_ex(myht, &pos)) {
      36. i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
      37. if (i == HASH_KEY_NON_EXISTANT)
      38. ブレーク;
      39. if (zend_hash_get_current_data_ex(myht, (void **) &data, &pos) == SUCCESS) {
      40. tmp_ht = HASH_OF(*data);
      41. if (tmp_ht) {
      42. tmp_ht->nApplyCount++;
      43. }
      44. if (r == PHP_JSON_OUTPUT_ARRAY) {
      45. if (need_comma) {
      46. Smart_str_appendc(buf, ',');
      47. } else {
      48. need_comma = 1;
      49. }
      50. // buf中に追加します
      51. php_json_encode(buf, *data, options TSRMLS_CC);
      52. } else if (r == PHP_JSON_OUTPUT_OBJECT) {
      53. if (i == HASH_KEY_IS_STRING) {
      54. if (key[0] == ' ' && Z_TYPE_PP(val) == IS_OBJECT) {
      55. /* 保護されたメンバーとプライベートメンバーをスキップします。 */
      56. if (tmp_ht) {
      57. tmp_ht->nApplyCount--;
      58. }
      59. 続けます。
      60. }
      61. if (need_comma) {
      62. Smart_str_appendc(buf, ',');
      63. } else {
      64. need_comma = 1;
      65. }
      66. json_escape_string(buf, key, key_len - 1, options & ~PHP_JSON_NUMERIC_CHECK TSRMLS_CC);
      67. smart_str_appendc(buf, ':');
      68. php_json_encode(buf, *data, options TSRMLS_CC);
      69. } else {
      70. if (need_comma) {
      71. Smart_str_appendc(buf, ',');
      72. } else {
      73. need_comma = 1;
      74. }
      75. smart_str_appendc(buf, '"');
      76. smart_str_append_long(buf, (long)index);
      77. smart_str_appendc(buf, '"');
      78. smart_str_appendc(buf, ':');
      79. php_json_encode(buf, *data, options TSRMLS_CC);
      80. }
      81. }
      82. if (tmp_ht) {
      83. tmp_ht->nApplyCount--;
      84. }
      85. }
      86. }
      87. }
      88. //结束标签
      89. if (r == PHP_JSON_OUTPUT_ARRAY) {
      90. Smart_str_appendc(buf, ']');
      91. } else {
      92. Smart_str_appendc(buf, '}');
      93. }
      94. }
      复制代コード

      通简单分析、证明了一问题、跟我上面用sprintf的方法其实是一样的,都是拼接字串,

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

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

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