Phpjson_encode Application Analysis

Source: Internet
Author: User
Phpjson_encode Application Analysis

  1. Static PHP_FUNCTION (json_encode)
  2. {
  3. Zval * parameter;
  4. Smart_str buf = {0 };
  5. Long options = 0;
  6. If (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "z | l", & parameter, & options) = FAILURE ){
  7. Return;
  8. }
  9. JSON_G (error_code) = PHP_JSON_ERROR_NONE;
  10. Php_json_encode (& buf, parameter, options TSRMLS_CC );
  11. ZVAL_STRINGL (return_value, buf. c, buf. len, 1 );
  12. Smart_str_free (& buf );
  13. }

JSON_G (error_code) = PHP_JSON_ERROR_NONE; is a defined json error. This error can be obtained through the json_last_error function. have you used it? I have never used it. Php_json_encode is the main operation

  1. PHP_JSON_API void php_json_encode (smart_str * buf, zval * val, int options TSRMLS_DC )/*{{{*/
  2. {
  3. Switch (Z_TYPE_P (val ))
  4. {
  5. Case IS_NULL:
  6. Smart_str_appendl (buf, "null", 4); // output NULL
  7. Break;
  8. Case IS_BOOL:
  9. If (Z_BVAL_P (val )){
  10. Smart_str_appendl (buf, "true", 4); // outputs true
  11. } Else {
  12. Smart_str_appendl (buf, "false", 5); // outputs false
  13. }
  14. Break;
  15. Case IS_LONG:
  16. Smart_str_append_long (buf, Z_LVAL_P (val); // output the value of the long integer.
  17. Break;
  18. Case IS_DOUBLE:
  19. {
  20. Char * d = NULL;
  21. Int len;
  22. Double dbl = Z_DVAL_P (val );
  23. If (! Zend_isinf (dbl )&&! Zend_isnan (dbl) {// non-endless
  24. Len = spprintf (& d, 0, "%. * k", (int) EG (precision), dbl );
  25. Smart_str_appendl (buf, d, len );
  26. Efree (d );
  27. } Else {
  28. Php_error_docref (NULL TSRMLS_CC, E_WARNING, "double %. 9g does not conform to the JSON spec, encoded as 0", dbl );
  29. Smart_str_appendc (buf, '0 ');
  30. }
  31. }
  32. Break;
  33. Case IS_STRING: // string
  34. Json_escape_string (buf, Z_STRVAL_P (val), Z_STRLEN_P (val), options TSRMLS_CC );
  35. Break;
  36. Case IS_ARRAY: // array and object
  37. Case IS_OBJECT:
  38. Json_encode_array (buf, & val, options TSRMLS_CC );
  39. Break;
  40. Default:
  41. Php_error_docref (NULL TSRMLS_CC, E_WARNING, "type is unsupported, encoded as null ");
  42. Smart_str_appendl (buf, "null", 4 );
  43. Break;
  44. }
  45. Return;
  46. }

Obviously, there will be corresponding cases based on different types. The most complex types are string, array, and object. arrays and objects are the same operation. Let's take a look at the string first. it's very long. comments are directly written in the code.

  1. // Options should be supported only after version 5.3. the binary mask composed of the following constants: JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, signature, JSON_NUMERIC_CHECK, signature, expires, JSON_FORCE_OBJECT, and signature. although I have never used it...
  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 us;
  6. Unsigned short * utf16;
  7. If (len = 0) {// if the length is 0, double quotation marks are returned directly ""
  8. Smart_str_appendl (buf, "\" \ "", 2 );
  9. Return;
  10. }
  11. If (options & PHP_JSON_NUMERIC_CHECK) {// check whether the number is 0-9. if it is a number, the data is directly returned as long or double.
  12. Double d;
  13. Int type;
  14. Long p;
  15. If (type = is_numeric_string (s, len, & p, & d, 0 ))! = 0 ){
  16. If (type = IS_LONG ){
  17. Smart_str_append_long (buf, p );
  18. } Else if (type = IS_DOUBLE ){
  19. If (! Zend_isinf (d )&&! Zend_isnan (d )){
  20. Char * tmp;
  21. Int l = spprintf (& tmp, 0, "%. * k", (int) EG (precision), d );
  22. Smart_str_appendl (buf, tmp, l );
  23. Efree (tmp );
  24. } Else {
  25. Php_error_docref (NULL TSRMLS_CC, E_WARNING, "double %. 9g does not conform to the JSON spec, encoded as 0", d );
  26. Smart_str_appendc (buf, '0 ');
  27. }
  28. }
  29. Return;
  30. }
  31. }
  32. Utf16 = (unsigned short *) safe_emalloc (len, sizeof (unsigned short), 0 );
  33. Len = utf8_to_utf16 (utf16, s, len); // the input value is converted to the corresponding Dec code once, for example, 1 is 49 and a is 97, save it to utf16.
  34. If (len <= 0) {// if len is smaller than 0, an error occurs. If you use json_encode to process GBK encoding, it will be suspended here.
  35. If (utf16 ){
  36. Efree (utf16 );
  37. }
  38. If (len <0 ){
  39. JSON_G (error_code) = PHP_JSON_ERROR_UTF8;
  40. If (! PG (display_errors )){
  41. Php_error_docref (NULL TSRMLS_CC, E_WARNING, "Invalid UTF-8 sequence in argument ");
  42. }
  43. Smart_str_appendl (buf, "null", 4 );
  44. } Else {
  45. Smart_str_appendl (buf, "\" \ "", 2 );
  46. }
  47. Return;
  48. }
  49. Smart_str_appendc (buf, '"'); // input \"
  50. // The following code escapes special characters, such as double quotation marks and backslash.
  51. While (pos <len)
  52. {
  53. Us = utf16 [pos ++];
  54. Switch (us)
  55. {
  56. Case '"':
  57. If (options & PHP_JSON_HEX_QUOT ){
  58. Smart_str_appendl (buf, "\ u0022", 6 );
  59. } Else {
  60. Smart_str_appendl (buf, "\\\" ", 2 );
  61. }
  62. Break;
  63. Case '\\':
  64. Smart_str_appendl (buf, "\\\\", 2 );
  65. Break;
  66. Case '/':
  67. Smart_str_appendl (buf, "\\/", 2 );
  68. Break;
  69. Case '\ B ':
  70. Smart_str_appendl (buf, "\ B", 2 );
  71. Break;
  72. Case '\ f ':
  73. Smart_str_appendl (buf, "\ f", 2 );
  74. Break;
  75. Case '\ n ':
  76. Smart_str_appendl (buf, "\ n", 2 );
  77. Break;
  78. Case '\ r ':
  79. Smart_str_appendl (buf, "\ r", 2 );
  80. Break;
  81. Case '\ t ':
  82. Smart_str_appendl (buf, "\ t", 2 );
  83. Break;
  84. Case '<':
  85. If (options & PHP_JSON_HEX_TAG ){
  86. Smart_str_appendl (buf, "\ u003C", 6 );
  87. } Else {
  88. Smart_str_appendc (buf, '<');
  89. }
  90. Break;
  91. Case '> ':
  92. If (options & PHP_JSON_HEX_TAG ){
  93. Smart_str_appendl (buf, "\ u003E", 6 );
  94. } Else {
  95. Smart_str_appendc (buf, '> ');
  96. }
  97. Break;
  98. Case '&':
  99. If (options & PHP_JSON_HEX_AMP ){
  100. Smart_str_appendl (buf, "\ u0026", 6 );
  101. } Else {
  102. Smart_str_appendc (buf ,'&');
  103. }
  104. Break;
  105. Case '\'':
  106. If (options & PHP_JSON_HEX_APOS ){
  107. Smart_str_appendl (buf, "\ u0027", 6 );
  108. } Else {
  109. Smart_str_appendc (buf ,'\'');
  110. }
  111. Break;
  112. Default: // until here, the value will be appended to the buf without special characters
  113. If (us> = ''& (us & 127) = us ){
  114. Smart_str_appendc (buf, (unsigned char) us );
  115. } Else {
  116. Smart_str_appendl (buf, "\ u", 2 );
  117. Us = REVERSE16 (us );
  118. Smart_str_appendc (buf, digits [us & (1 <4)-1)]);
  119. Us> = 4;
  120. Smart_str_appendc (buf, digits [us & (1 <4)-1)]);
  121. Us> = 4;
  122. Smart_str_appendc (buf, digits [us & (1 <4)-1)]);
  123. Us> = 4;
  124. Smart_str_appendc (buf, digits [us & (1 <4)-1)]);
  125. }
  126. Break;
  127. }
  128. }
  129. Smart_str_appendc (buf, '"'); // End double quotation marks.
  130. Efree (utf16 );
  131. }

Let's take a look at Arrays and objects, which is also very simple,

  1. Static void json_encode_array (smart_str * buf, zval ** val, int options TSRMLS_DC )/*{{{*/
  2. {
  3. Int I, r;
  4. HashTable * myht;
  5. If (Z_TYPE_PP (val) = IS_ARRAY ){
  6. Myht = HASH_OF (* val );
  7. R = (options & 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, "recursion detected ");
  14. Smart_str_appendl (buf, "null", 4 );
  15. Return;
  16. }
  17. // Start tag
  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 ** data;
  28. Ulong index;
  29. Uint key_len;
  30. HashPosition pos;
  31. HashTable * tmp_ht;
  32. Int need_comma = 0;
  33. Zend_hash_internal_pointer_reset_ex (myht, & pos );
  34. // Convenient hash table
  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. Break;
  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 the value to the 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] = '\ 0' & Z_TYPE_PP (val) = IS_OBJECT ){
  55. /* Skip protected and private members .*/
  56. If (tmp_ht ){
  57. Tmp_ht-> nApplyCount --;
  58. }
  59. Continue;
  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. // End tag
  89. If (r = PHP_JSON_OUTPUT_ARRAY ){
  90. Smart_str_appendc (buf, ']');
  91. } Else {
  92. Smart_str_appendc (buf ,'}');
  93. }
  94. }

After a simple analysis, it is proved that the sprintf method is the same as that used above, and all of them are concatenated strings,

In addition, sprintf should be encouraged to splice json formats for performance purposes,

Because json_encode performs many loop operations, and the consumed performance is linear O (n ).

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.