Json_encode analysis of PHP. I don't need to mention the advantages of json. I have a habit. when I output json, I like to use sprintf to splice it into json format. I was told by a friend that it was not standard two days ago, the json_encode must be used to generate the advantage of json,
I like to use sprintf to spell json format when outputting json,
Two days ago, I was told that it was not standard. The standard json format must be generated using json_encode. of course, I am very depressed,
After so many years of use, I just learned that this is not a standard. since I am not a standard, is the above standard json format?
{A: 'ABC '}
{'A': 'ABC '}
{A: "abc "}
{"A": "abc "}
We all know that only the fourth type is the standard json format.
I am doing this
$ Ret_json = '{"% s": "% s "}';
Echo json_encode ($ ret_json, "a", "abc ");
It must also comply with standards.
In this case, I have to answer the question. what is the difference in the json format generated by json_encode?
Code on
Static PHP_FUNCTION (json_encode)
{
Zval * parameter;
Smart_str buf = {0 };
Long options = 0;
If (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "z | l", & parameter, & options) = FAILURE ){
Return;
}
JSON_G (error_code) = PHP_JSON_ERROR_NONE;
Php_json_encode (& buf, parameter, options TSRMLS_CC );
ZVAL_STRINGL (return_value, buf. c, buf. len, 1 );
Smart_str_free (& buf );
}
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 this error? I have never used it.
Php_json_encode is the main operation
PHP_JSON_API void php_json_encode (smart_str * buf, zval * val, int options TSRMLS_DC )/*{{{*/
{
Switch (Z_TYPE_P (val ))
{
Case IS_NULL:
Smart_str_appendl (buf, "null", 4); // output NULL
Break;
Case IS_BOOL:
If (Z_BVAL_P (val )){
Smart_str_appendl (buf, "true", 4); // outputs true
} Else {
Smart_str_appendl (buf, "false", 5); // outputs false
}
Break;
Case IS_LONG:
Smart_str_append_long (buf, Z_LVAL_P (val); // output the value of the long integer.
Break;
Case IS_DOUBLE:
{
Char * d = NULL;
Int len;
Double dbl = Z_DVAL_P (val );
If (! Zend_isinf (dbl )&&! Zend_isnan (dbl) {// non-endless
Len = spprintf (& d, 0, "%. * k", (int) EG (precision), dbl );
Smart_str_appendl (buf, d, len );
Efree (d );
} Else {
Php_error_docref (NULL TSRMLS_CC, E_WARNING, "double %. 9g does not conform to the JSON spec, encoded as 0", dbl );
Smart_str_appendc (buf, '0 ');
}
}
Break;
Case IS_STRING: // string
Json_escape_string (buf, Z_STRVAL_P (val), Z_STRLEN_P (val), options TSRMLS_CC );
Break;
Case IS_ARRAY: // array and object
Case IS_OBJECT:
Json_encode_array (buf, & val, options TSRMLS_CC );
Break;
Default:
Php_error_docref (NULL TSRMLS_CC, E_WARNING, "type is unsupported, encoded as null ");
Smart_str_appendl (buf, "null", 4 );
Break;
}
Return;
}
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.
// 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...
Static void json_escape_string (smart_str * buf, char * s, int len, int options TSRMLS_DC )/*{{{*/
{
Int pos = 0;
Unsigned short us;
Unsigned short * utf16;
If (len = 0) {// if the length is 0, double quotation marks are returned directly ""
Smart_str_appendl (buf, "\" \ "", 2 );
Return;
}
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.
Double d;
Int type;
Long p;
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 )){
Char * tmp;
Int l = spprintf (& tmp, 0, "%. * k", (int) EG (precision), d );
Smart_str_appendl (buf, tmp, l );
Efree (tmp );
} Else {
Php_error_docref (NULL TSRMLS_CC, E_WARNING, "double %. 9g does not conform to the JSON spec, encoded as 0", d );
Smart_str_appendc (buf, '0 ');
}
}
Return;
}
}
Utf16 = (unsigned short *) safe_emalloc (len, sizeof (unsigned short), 0 );
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.
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.
If (utf16 ){
Efree (utf16 );
}
If (len <0 ){
JSON_G (error_code) = PHP_JSON_ERROR_UTF8;
If (! PG (display_errors )){
Php_error_docref (NULL TSRMLS_CC, E_WARNING, "Invalid UTF-8 sequence in argument ");
}
Smart_str_appendl (buf, "null", 4 );
} Else {
Smart_str_appendl (buf, "\" \ "", 2 );
}
Return;
}
Smart_str_appendc (buf, '"'); // input \"
// The following code escapes special characters, such as double quotation marks and backslash.
While (pos <len)
{
Us = utf16 [pos ++];
Switch (us)
{
Case '"':
If (options & PHP_JSON_HEX_QUOT ){
Smart_str_appendl (buf, "\ u0022", 6 );
} Else {
Smart_str_appendl (buf, "\\\" ", 2 );
}
Break;
Case '\\':
Smart_str_appendl (buf, "\\\\", 2 );
Break;
Case '/':
Smart_str_appendl (buf, "\\/", 2 );
Break;
Case '\ B ':
Smart_str_appendl (buf, "\ B", 2 );
Break;
Case '\ f ':
Smart_str_appendl (buf, "\ f", 2 );
Break;
Case '\ n ':
Smart_str_appendl (buf, "\ n", 2 );
Break;
Case '\ r ':
Smart_str_appendl (buf, "\ r", 2 );
Break;
Case '\ t ':
Smart_str_appendl (buf, "\ t", 2 );
Break;
Case '<':
If (options & PHP_JSON_HEX_TAG ){
Smart_str_appendl (buf, "\ u003C", 6 );
} Else {
Smart_str_appendc (buf, '<');
}
Break;
Case '> ':
If (options & PHP_JSON_HEX_TAG ){
Smart_str_appendl (buf, "\ u003E", 6 );
} Else {
Smart_str_appendc (buf, '> ');
}
Break;
Case '&':
If (options & PHP_JSON_HEX_AMP ){
Smart_str_appendl (buf, "\ u0026", 6 );
} Else {
Smart_str_appendc (buf ,'&');
}
Break;
Case '\'':
If (options & PHP_JSON_HEX_APOS ){
Smart_str_appendl (buf, "\ u0027", 6 );
} Else {
Smart_str_appendc (buf ,'\'');
}
Break;
Default: // until here, the value will be appended to the buf without special characters
If (us> = ''& (us & 127) = us ){
Smart_str_appendc (buf, (unsigned char) us );
} Else {
Smart_str_appendl (buf, "\ u", 2 );
Us = REVERSE16 (us );
Smart_str_appendc (buf, digits [us & (1 <4)-1)]);
Us> = 4;
Smart_str_appendc (buf, digits [us & (1 <4)-1)]);
Us> = 4;
Smart_str_appendc (buf, digits [us & (1 <4)-1)]);
Us> = 4;
Smart_str_appendc (buf, digits [us & (1 <4)-1)]);
}
Break;
}
}
Smart_str_appendc (buf, '"'); // End double quotation marks.
Efree (utf16 );
}
Let's take a look at Arrays and objects, which is also very simple,
Static void json_encode_array (smart_str * buf, zval ** val, int options TSRMLS_DC )/*{{{*/
{
Int I, r;
HashTable * myht;
If (Z_TYPE_PP (val) = IS_ARRAY ){
Myht = HASH_OF (* val );
R = (options & PHP_JSON_FORCE_OBJECT )? PHP_JSON_OUTPUT_OBJECT: json_determine_array_type (val TSRMLS_CC );
} Else {
Myht = Z_OBJPROP_PP (val );
R = PHP_JSON_OUTPUT_OBJECT;
}
If (myht & myht-> nApplyCount> 1 ){
Php_error_docref (NULL TSRMLS_CC, E_WARNING, "recursion detected ");
Smart_str_appendl (buf, "null", 4 );
Return;
}
// Start tag
If (r = PHP_JSON_OUTPUT_ARRAY ){
Smart_str_appendc (buf ,'[');
} Else {
Smart_str_appendc (buf ,'{');
}
I = myht? Zend_hash_num_elements (myht): 0;
If (I> 0)
{
Char * key;
Zval ** data;
Ulong index;
Uint key_len;
HashPosition pos;
HashTable * tmp_ht;
Int need_comma = 0;
Zend_hash_internal_pointer_reset_ex (myht, & pos );
// Convenient hash table
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)
Break;
If (zend_hash_get_current_data_ex (myht, (void **) & data, & pos) = SUCCESS ){
Tmp_ht = HASH_OF (* data );
If (tmp_ht ){
Tmp_ht-> nApplyCount ++;
}
If (r = PHP_JSON_OUTPUT_ARRAY ){
If (need_comma ){
Smart_str_appendc (buf ,',');
} Else {
Need_comma = 1;
}
// Append the value to the 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] = '\ 0' & Z_TYPE_PP (val) = IS_OBJECT ){
/* Skip protected and private members .*/
If (tmp_ht ){
Tmp_ht-> nApplyCount --;
}
Continue;
}
If (need_comma ){
Smart_str_appendc (buf ,',');
} Else {
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 );
} Else {
If (need_comma ){
Smart_str_appendc (buf ,',');
} Else {
Need_comma = 1;
}
Smart_str_appendc (buf ,'"');
Smart_str_append_long (buf, (long) index );
Smart_str_appendc (buf ,'"');
Smart_str_appendc (buf ,':');
Php_json_encode (buf, * data, options TSRMLS_CC );
}
}
If (tmp_ht ){
Tmp_ht-> nApplyCount --;
}
}
}
}
// End tag
If (r = PHP_JSON_OUTPUT_ARRAY ){
Smart_str_appendc (buf, ']');
} Else {
Smart_str_appendc (buf ,'}');
}
}
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,
Parser. I like to use sprintf to splice the json format when outputting json. I was told by a friend two days ago that it was not standard and that json_encode must be used to generate the standard...