> 백엔드 개발 > PHP 튜토리얼 > PHP json_encode 애플리케이션 분석

PHP json_encode 애플리케이션 분석

WBOY
풀어 주다: 2016-07-25 09:04:22
원래의
1064명이 탐색했습니다.
  1. static PHP_FUNCTION(json_encode)
  2. {
  3. zval *parameter;
  4. smart_str buf =
  5. long options = 0; 🎜>
  6. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", ¶meter, &options) == FAILURE) {
  7. return
  8. }
  9. JSON_G(error_code) = PHP_JSON_ERROR_NONE ;
  10. php_json_encode(&buf, 매개변수, 옵션 TSRMLS_CC)
  11. ZVAL_STRINGL(return_value, buf.c, buf.len, 1)
  12. 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) /* {{{ */
  1. {
  2. 스위치( Z_TYPE_P(val))
  3. {
  4. case IS_NULL:
  5. smart_str_appendl(buf, "null", 4) //출력 NULL
  6. break; if (Z_BVAL_P(val)) {
  7. smart_str_appendl(buf, "true", 4);//true 출력
  8. } 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));//Long 정수 값 출력
  14. break; 케이스 IS_DOUBLE:
  15. {
  16. char *d = NULL;
  17. int len ​​
  18. double dbl = Z_DVAL_P(val)
  19. if (!zend_isinf(dbl) && !zend_isnan( dbl )) {//무한대
  20. len = spprintf(&d, 0, "%.*k", (int) EG(정밀도), dbl)
  21. smart_str_appendl(buf, d, len);
  22. efree(d);
  23. } else {
  24. php_error_docref(NULL TSRMLS_CC, E_WARNING, "double %.9g는 0으로 인코딩된 JSON 사양을 따르지 않습니다.", dbl); buf , '0')
  25. }
  26. }
  27. break;
  28. case IS_STRING://string
  29. json_escape_string(buf, Z_STRVAL_P(val), Z_STRLEN_P(val), options TSRMLS_CC);
  30. 중단
  31. 케이스 IS_ARRAY://배열 및 개체
  32. 케이스 IS_OBJECT:
  33. json_encode_array(buf, &val, 옵션 TSRMLS_CC)
  34. 기본값:
  35. php_error_docref(NULL TSRMLS_CC, E_WARNING, "유형이 지원되지 않습니다. null로 인코딩됩니다.")
  36. smart_str_appendl(buf, "null", 4)
  37. break; >
  38. 반환
  39. }
  40. 코드 복사
  41. 분명히 유형에 따라 해당되는 경우가 있을 것입니다. 가장 복잡한 유형은 문자열, 배열 및 객체입니다. 배열과 객체는 동일한 작업입니다. 먼저 문자열을 살펴보겠습니다. 매우 길고 주석이 코드에 직접 작성되어 있습니다.

    1. //옵션은 JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASH ES, 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
    5. unsigned short
    6. unsigned short *utf16;
    7. if (len == 0) {//길이가 0이면 큰따옴표를 직접 반환합니다. ""
    8. smart_str_appendl(buf, """", 2); 🎜> return;
    9. }
    10. if (options & PHP_JSON_NUMERIC_CHECK) {//0부터 9까지의 숫자인지 확인합니다. 숫자인 경우 데이터는 long 또는 이중 유형.
    11. double d;
    12. int type;
    13. long p;
    14. if ((type = is_numeric_string(s, len, &p, &d, 0)) != 0) 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)) {
    18. char *tmp;
    19. int l = spprintf(&tmp, 0, "%.*k", (int) EG(정밀도), d)
    20. smart_str_appendl(buf, tmp, l); > efree(tmp);
    21. } else {
    22. php_error_docref(NULL TSRMLS_CC, E_WARNING, "double %.9g는 0으로 인코딩된 JSON 사양을 따르지 않습니다.", d); '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); //입력한 값은 한 번 처리되어 해당 Dec 코드로 변환됩니다. 예를 들어 1은 49이고 a는 97입니다. utf16으로.
    30. if (len <= 0) {//len이 0보다 작으면 오류가 발생합니다. json_encode를 사용하여 GBK 인코딩을 처리하면 여기서 끊깁니다.
    31. if (utf16) {
    32. efree(utf16);
    33. }
    34. if (len < 0) {
    35. JSON_G(error_code) = PHP_JSON_ERROR_UTF8> if (!PG(display_errors) )) {
    36. php_error_docref(NULL TSRMLS_CC, E_WARNING, "인수에 잘못된 UTF-8 시퀀스")
    37. }
    38. smart_str_appendl(buf, "null", 4); > smart_str_appendl(buf, """", 2);
    39. }
    40. return
    41. }
    42. smart_str_appendc(buf, '"'); //" 입력
    43. //다음 코드는 큰따옴표, 백슬래시 등과 같은 일부 특수 문자를 이스케이프하는 것입니다.
    44. while (pos < len)
    45. {
    46. us = utf16[pos ]
    47. 스위치(우리)
    48. {
    49. case '"':
    50. if (options & PHP_JSON_HEX_QUOT) {
    51. smart_str_appendl(buf, "\u0022", 6);
    52. } else {
    53. smart_str_appendl(buf, "\"", 2);
    54. }
    55. break;
    56. case '\':
    57. smart_str_appendl(buf, "\\", 2);
    58. break;
    59. 케이스 '/':
    60. smart_str_appendl(buf, "\/", 2)
    61. break;
    62. 케이스 'b':
    63. smart_str_appendl(buf , " \b", 2);
    64. 중단;
    65. 케이스 'f':
    66. smart_str_appendl(buf, "\f", 2);
    67. 중단;
    68. 케이스 'n':
    69. smart_str_appendl(buf, "\n", 2);
    70. break;
    71. case 'r':
    72. smart_str_appendl(buf, "\r", 2 );
    73. break;
    74. case 't':
    75. smart_str_appendl(buf, "\t", 2)
    76. break;
    77. case '<':
    78. if (옵션 & PHP_JSON_HEX_TAG) {
    79. smart_str_appendl(buf, "\u003C", 6);
    80. } else {
    81. smart_str_appendc(buf, '<')
    82. }
    83. break ;
    84. 케이스 '>':
    85. if (옵션 & PHP_JSON_HEX_TAG) {
    86. smart_str_appendl(buf, "\u003E", 6)
    87. } else {
    88. smart_str_appendc (buf , '>');
    89. }
    90. break;
    91. case '&':
    92. if (options & PHP_JSON_HEX_AMP) {
    93. smart_str_appendl(buf, "\u0026" , 6 );
    94. } else {
    95. smart_str_appendc(buf, '&')
    96. }
    97. break
    98. case ''':
    99. if (options & PHP_JSON_HEX_APOS )
    100. smart_str_appendl(buf, "\u0027", 6);
    101. } else {
    102. smart_str_appendc(buf, ''')
    103. }
    104. break; //여기까지 특수문자가 없으면 buf
    105. if (us >= ' ' && (us & 127) == us) {
    106. smart_str_appendc(buf, ( 서명되지 않은 문자) 우리)
    107. }else {
    108. smart_str_appendl(buf, "\u", 2);
    109. us = REVERSE16(우리);
    110. smart_str_appendc(buf, digits[us & ((1 우리 >>= 4;
    111. smart_str_appendc(buf, 숫자[us & ((1 우리 >>= 4;
    112. smart_str_appendc(buf, 숫자[us & ((1 우리 >>= 4;
    113. smart_str_appendc(buf, 숫자[us & ((1 }
    114. 휴식;
    115. }
    116. }
    117. smart_str_appendc(buf, '"'); //结束 双引号。
    118. efree(utf16);
    119. }
    复aze代码

    배열과 객체도 매우 간단합니다.

    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. 우롱지수;
    29. uint key_len;
    30. HashPosition 위치;
    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. //将值append到 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. /* protected 및 private 멤버를 건너뜁니다. */
    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, 옵션 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, 옵션 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)을 제공합니다.



관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿