首頁 > 後端開發 > php教程 > php json_encode應用分析

php json_encode應用分析

WBOY
發布: 2016-07-25 09:04:22
原創
1046 人瀏覽過
因為 json_encode 會進行很多循環操作,而且所消耗的效能是線性的 O(n)。
  1. static PHP_FUNCTION(json_encode)
  2. {
  3. zval *parameter;
  4. smart_str buf = {0};
  5. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", ¶meter, &options) == FAILURE) {
  6. return;
  7. }
  8. php_json_encode(&buf, parameter, options TSRMLS_CC);
  9. ZVAL_STRINGL(return_value, buf.c, buf.len, 1);
  10. 🎜> }
  11. 複製程式碼
  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) /* {str* Z_TYPE_P(val))

{
case IS_NULL:
smart_str_appendl(buf, "null", 4); //輸出NULL
    break:
  1. case IS_BOOL:
  2. if (Z_BVAL_P(val)) {
  3. smart_str_appendl(buf, "true", 4);//輸出true
  4. } else {
  5. smart_str_appendl(buf, "false", 5);
  6. }
  7. break;
  8. }
  9. break;
  10. case IS_LONG:
  11. smart_str_append_long(buf, Z_LVAL_P(val));//輸出長整形的值
  12. break;
  13. >; IS_DOUBLE:
  14. {
  15. char *d = NULL;
  16. int len;
  17. double dbl = Z_DVAL_P(val);
  18. if (!zend_isinf(val);
  19. if (!zend_isinf(dbl) && ! )) {//非無窮無盡
  20. len = spprintf(&d, 0, "%.*k", (int) EG(precision), dbl);
  21. smart_str_appendl(buf, d, len);
  22. efree(d);
  23. } else {
  24. php_error_docref(NULL TSRMLS_CC, E_WARNING, "double %.9g does not conform to the JSON spec, encoded as 0", dblm }
  25. }
  26. break;
  27. case IS_STRING://字串
  28. json_escape_string(buf, Z_STRVAL_P(val), Z_STRLEN_P(val), opbuf TSRMLS_CC);
  29. break;
  30. case IS_ARRAY://陣列與物件
  31. case IS_OBJECT:
  32. json_encode_array(buf, &val, options TSRMLS_CC) default:
  33. php_error_docref(NULL TSRMLS_CC, E_WARNING, "type is unsupported, encoded as null");
  34. smart_str_appendl(buf, "nullull");
  35. smart_str_appendl(buf, "nullull"); >
  36. return;
  37. }
  38. 複製程式碼
  39. 很明顯,根據不同的類型,會有對應的case。 最複雜的是 字串 、陣列 、物件這三種類型,陣列和物件是同一種操作。 先看看字串吧,很長,註解直接寫在程式碼裡。

    1. //options應該是5.3版本之後才支援的,由以下常數組成的二進位遮罩: JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSLSON_MER_AMP ASHES, JSON_FORCE_OBJECT, JSON_UNESCAPED_UNICODE.雖然我沒用過。 。 。
    2. static void json_escape_string(smart_str *buf, char *s, int len, int options TSRMLS_DC) /* {{{ */
    3. {
    4. int pos = 0; > unsigned short *utf16;
    5. if (len == 0) {//如果長度為0,則直接回傳雙引號""
    6. smart_str_appendl(buf, """", 2);
    7. return;
    8. }
    9. if (options & PHP_JSON_NUMERIC_CHECK) {//偵測是否為0-9的數字,如果是數字,那麼就會直接把資料傳回為long或double型別。
    10. double d;
    11. int type;
    12. long p;
    13. if ((type = is_numeric_string(s, len, &p, &d, 0)) != 0) {
    14. if (type == IS_LONG) {
    15. smart_str_append_long(buf, p);
    16. } else if (type == IS_DOUBLE) {
    17. if (!zend_isinf(d) && !zend_isnan(d)) { 🎜> char *tmp;
    18. int l = spprintf(&tmp, 0, "%.*k", (int) EG(precision), d);
    19. smart_str_appendl(buf, tmp, l);
    20. efree(tmp);
    21. } else {
    22. php_error_docref(NULL TSRMLS_CC, E_WARNING, "double %.9g does not conform to the JSON spec, encoded as 0", d3); '0');
    23. }
    24. }
    25. return;
    26. }
    27. }
    28. utf16 = (unsigned short *) safe_emalloc(lenlen, sort ), 0);
    29. len = utf8_to_utf16(utf16, s, len); //這裡會對你輸入的值一次處理轉成對應的Dec碼,例如1是49,a是97這樣的,保存到utf16中。
    30. if (len if (utf16) {
    31. efree(utf16);
    32. }
    33. if (len JSON_G(error_code) = PHP_JorsSON_ERROR_UTF8
    34. ifors_code); ) {
    35. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid UTF-8 sequence in argument");
    36. }
    37. smart_str_appendl(buf, "null", 4); smart_str_appendl(buf, """", 2);
    38. }
    39. return;
    40. }
    41. smart_str_appendc(buf, '"'); //輸入"
    42. //下面這段程式碼就是將一些特殊字元轉義如雙引號,反斜線等等
    43. while (pos {
    44. us = utf16[pos++];
    45. switch (us)
    46. {
    47. case '"':
    48. if (options & PHP_JSON_HEX_QUOT) {
    49. smart_str_appendl(buf, "\u0022", 6);
    50. } > smart_str_appendl(buf, "\"", 2);
    51. }
    52. break;
    53. case '\':
    54. smart_str_appendl(buf, "\\", 2); > break;
    55. case '/':
    56. smart_str_appendl(buf, "\/", 2);
    57. break;
    58. case 'b':
    59. smart_str_str_str \b", 2);
    60. break;
    61. case 'f':
    62. smart_str_appendl(buf, "\f", 2);
    63. break;
    64. case 'n':
    65. smart_str_appendl(buf, "\n", 2);
    66. break;
    67. case 'r':
    68. smart_str_appendl(buf, "\r", 2);
    69. break;
    70. case 't':
    71. smart_str_appendl(buf, "\t", 2);
    72. break;
    73. case ' if (options & PHP_JSON_HEX_TAG) {
    74. smart_str_appendl(buf, "\u003C", 6);
    75. } else {
    76. smart_str_appendc(buf, '
    77. case '>':
    78. if (options & PHP_JSON_HEX_TAG) {
    79. smart_str_appendl(buf, "\u003E", 6);
    80. } ');
    81. }
    82. break;
    83. case '&':
    84. if (options & PHP_JSON_HEX_AMP) {
    85. smart_str_appendl(buf, "\u0026", 66); > } else {
    86. smart_str_appendc(buf, '&');
    87. }
    88. break;
    89. case ''':
    90. if (options & PHP_JSON_HEXL_APOS (buf, "\u0027", 6);
    91. } else {
    92. smart_str_appendc(buf, ''');
    93. }
    94. break;
    95. default: //一直到這裡,沒有特殊字元就會把值append到buf
    96. if (us >= ' ' && (us & 127) == us) {
    97. smart_str_appendc(buf, (unsigned char) us);
    98. }else {
    99. smart_str_appendl(buf, "\u", 2);
    100. 我們= REVERSE16(我們);
    101. smart_str_appendc(buf,digits[us & ((1 我們>>= 4;
    102. smart_str_appendc(buf, 數字[us & ((1 我們>>= 4;
    103. smart_str_appendcc (buf, 數字[us & ((1 我們>>= 4;
    104. smart_str_appendc(buf, 數字[us & ((1 }
    105. 休息;
    106. }
    107. }
    108. smart_str_appendc(buf, '"'); //結束雙引號。
    109. efree(utf16);
    110. }
    複製程式碼

    再來看看陣列和對象,也很簡單,

    1. static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC) /* {{{ */
    2. { 雜湊表*myht;
    3. if (Z_TYPE_PP(val) == IS_ARRAY) {
    4. myht = HASH_OF(*val);
    5. r = (選項& PHP_JSON_FORCE_OBJ) : json_define_array_type(val TSRMLS_CC);
    6. } else {
    7. myht = Z_OBJPROP_PP(val);
    8. r = PHP_JSON_OUTPUT_OBJECT;
    9. }
    10. php_error_docref(NULL TSRMLS_CC, E_WARNING, "偵測到遞迴");
    11. smart_str_appendl(buf, "null", 4);
    12. 回傳;
    13. }
    14. } if (r == PHP_JSON_OUTPUT_ARRAY) {
    15. smart_str_appendc(buf, '[');
    16. } else {
    17. smart_str_appendc(buf, '{');我=我的? zend_hash_num_elements(myht) : 0;
    18. if (i > 0)
    19. {
    20. char *key;
    21. zval **數據;
    22. ulong索引;
    23. uint key_len;
    24. HashPosition pos;
    25. 雜湊表*tmp_ht;
    26. int need_comma = 0;
    27. zend_hash_internal_pointer_reset_ex(myht, &pos);
    28. for運輸; zend_hash_move_forward_ex(myht, &pos)) {
    29. i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
    30. if (i == HASH_len, &index, 0, &pos);
    31. if (i == HASH_KEY_NON_ASH_ANT; if (zend_hash_get_current_data_ex(myht, (void **) &data, &pos) == SUCCESS) {
    32. tmp_ht = HASH_OF(*data);
    33. if (tmp_ht) {
    34. tmp_ht-> }
    35. if (r == PHP_JSON_OUTPUT_ARRAY) {
    36. if (r == PHP_JSON_OUTPUT_ARRAY) {
    37. if (need_comma) {
    38. smart_str_appendc(buf, ',');
    39. } else { <.com> }
    40. //將值追加到buf 中
    41. php_json_encode(buf, *data, options TSRMLS_CC);
    42. } else if (r == PHP_JSON_OUTPUT_OBJECT) {
    43. _liter {
    44. if (key[0] == ' ' && Z_TYPE_PP(val) == IS_OBJECT) {
    45. /* 跳過受保護和私有成員。 */
    46. if (tmp_ht) {
    47. tmp_ht->nApplyCount--;
    48. }
    49. 繼續;
    50. }
    51. if (need_comma) {
    52. smart_str , ',');
    53. } else {
    54. need_comma = 1;
    55. }
    56. json_escape_string(buf, key, key_len - 1, options & ~PHP_JSON_NUMERy_PCK; (buf, ':');
    57. php_json_encode(buf, *data, options TSRMLS_CC);
    58. } else {
    59. if (need_comma) {
    60. smart_str. ;
    61. } else {
    62. need_comma = 1;
    63. }
    64. smart_str_appendc(buf, '"');
    65. smart_str_append_long(buf, (long) 索引);
    66. smart_str_appendc(buf, '"');
    67. smart_strm' );
    68. php_json_encode(buf, *data, options TSRMLS_CC);
    69. }
    70. }
    71. if (tmp_ht) {
    72. }
    73. if (tmp_ht) {
    74. > }
    75. }
    76. }
    77. }
    78. // 結束標籤
    79. if (r == PHP_JSON_OUTPUT_ARRAY) {
    80. smart_str_appendc(buf, ']');
    81. }
    82. smart_str_appendc(buf, '}');
    }
    }
    複製程式碼

    透過簡單的分析,說明了一個問題,相當於上面用sprintf的方法其實是一樣的,都是拼接字串,

    而且為了效能,更應該鼓勵用sprintf來拼接json格式,



相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板