json の利点については説明しません。
私には習慣があり、json を出力するときに sprintf を使用して json 形式に変換するのが好きです。
2 日前に友人が、これは標準ではないので、標準の json 形式を生成するには json_encode を使用する必要があると言いました。もちろん、私はとても落ち込んでいます。
何年も使ってきたので、これが標準ではないことに気づきました。私は標準ではないので、上記は標準のjson形式ですか?
{a : 'abc'}
{'a' : 'abc'}
{a : "abc"}
{"a" : "abc"}
ご存知のとおり、標準の json 形式は 4 番目のタイプのみです。
私はこれをします
$ret_json='{"%s":"%s"}';
echo json_encode($ret_json,"a","abc");
規格も満たしている必要があります。
この場合、さらに深く尋ねる必要があります。json_encode によって生成される json 形式の違いは何ですか?
コードをアップロードする
静的 PHP_FUNCTION(json_encode)
{
zval *パラメータ
smart_str buf = {0};
長いオプション = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", ¶meter, &options) == FAILURE) {
JSON_G(error_code) = PHP_JSON_ERROR_NONE;
php_json_encode(&buf, パラメータ, オプション TSRMLS_CC);
ZVAL_STRINGL(戻り値, buf.c, buf.len, 1);
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) /* {{{ */
{
スイッチ(Z_TYPE_P(val))
ケース IS_NULL:
’ ’ s ‐ 1 out 1 out through out through out through ‐ to ‐ ‐ ‐ ‐ ‐ Smart_str_appendl(buf, "null", 4); // NULL を出力します。
休憩
ケース IS_BOOL:
Smart_str_appendl(buf, "true", ;// true を出力します
️
smart_str_appendl(buf, "false", 5); // false を出力します
休憩
ケース IS_LONG:
" _P(val)); //長整数値を出力します
休憩
ケース IS_DOUBLE:
int int len;
double dbl = Z_DVAL_P(val);
if (!zend_isinf(dbl) && !zend_isnan(dbl)) {//非无穷尽
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 は JSON 仕様に準拠していません。0 としてエンコードされています", dbl);
Smart_str_appendc(buf, '0');
}
}
休憩。
case IS_STRING://文字串
json_escape_string(buf, Z_STRVAL_P(val), Z_STRLEN_P(val), options TSRMLS_CC);
休憩。
case IS_ARRAY://数组和对象
case IS_OBJECT:
json_encode_array(buf, &val, options TSRMLS_CC);
休憩。
デフォルト:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "型はサポートされていないため、null としてエンコードされています");
Smart_str_appendl(buf, "null", 4);
休憩。
}
戻る;
}
明らかに、さまざまなタイプに応じて、対応するケースが存在する可能性があります。
最終的なのは、文字列、数値集合、オブジェクトです。この 3 つの種類、数値集合とオブジェクトは同じ操作です。
先見文字列、長さ、注釈は代コードに直接書き込まれます。
//オプションは 5.3 バージョン以降にサポートされており、以下の常量構成による二項制: JSON_HEX_QUOT、JSON_HEX_TAG、JSON_HEX_AMP、JSON_HEX_APOS、JSON_NUMERIC_CHECK、JSON_PRETTY_PRINT、JSON_UNESCAPED_SLASHES、 ECT、JSON_UNESCAPED_UNICODE。虽然我不使用。。。
static void json_escape_string(smart_str *buf, char *s, int len, int options TSRMLS_DC) /* {{{ */
{
int pos = 0;
無署名でショートします。
unsigned short *utf16;
if (len == 0) {//如果长度範囲0,直接双引号 "" を返します
smart_str_appendl(buf, """", 2);
戻る;
}
If (options & PHP_JSON_NUMERIC_CHECK) {//0 から 9 までの数値であるかどうかを確認します。数値の場合、データはlong 型または double 型として直接返されます。
🎝
int 型;
長い p;
if ((type = is_numeric_string(s, len, &p, &d, 0)) != 0) {
to
smart_str_append_long(buf、p);
} else if (type == IS_DOUBLE) {
{
int l = spprintf(&tmp, 0, "%.*k", (int) EG(精度)、d);
smart_str_appendl(buf、tmp、l);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "double %.9g は 0 としてエンコードされています",
);
smart_str_appendc(buf、 '0');
}
}
utf16 = (unsigned short *)safe_emalloc(len, sizeof(unsigned short), 0);
len = utf8_to_utf16(utf16, s, len); //入力した値は 1 回処理され、1 は 49、a は 97 など、対応する 12 進コードに変換され、utf16 に保存されます。
if (len
if (utf16) {
efree(utf16);
}
if (len
JSON_G(error_code) = PHP_JSON_ERROR_UTF8;
_
php_error_docref(NULL TSRMLS_CC, E_WARNING, "引数の UTF-8 シーケンスが無効です");
Smart_str_appendl(buf, "null", 4);
} else {
Smart_str_appendl(buf, """", 2);
}
}
smart_str_appendc(buf, '"'); //「
」を入力
//次のコードは、二重引用符、バックスラッシュなどの一部の特殊文字をエスケープします。
while (pos
us = utf16[pos++];
スイッチ (私たち)
ケース「」」:
if(options&php_json_hex_quot){
smart_str_appendl(buf、 "\ u0022"、6);
smart_str_appendl(buf、 "\" "、2);
case '\':
Smart_str_appendl(buf, "\\", 2);
休憩;
ケース '/':
️ Smart_str_appendl(buf, "\/", 2);
ケース「b」:
smart_str_appendl(buf, "\b", 2);
ケース 'f':
Smart_str_appendl(buf, "\f", ;
休憩;
ケース「n」:
smart_str_appendl(buf, 2 );
ケース「r」:
smart_str_appendl(buf, 2 );
case 't':
Smart_str_appendl(buf, "\t", 2) ;
case '
if (オプション & PHP_JSON_HEX_TAG) {
Smart_str_appendl(buf, "\u003C", 6);
} else {
Smart_str_appendc(buf, '
}
休憩。
case '>':
if (オプション & PHP_JSON_HEX_TAG) {
Smart_str_appendl(buf, "\u003E", 6);
} else {
Smart_str_appendc(buf, '>');
}
休憩。
ケース '&':
if (オプション & PHP_JSON_HEX_AMP) {
Smart_str_appendl(buf, "\u0026", 6);
} else {
Smart_str_appendc(buf, '&');
}
休憩。
ケース「」:
if (オプション & PHP_JSON_HEX_APOS) {
Smart_str_appendl(buf, "\u0027", 6);
} else {
Smart_str_appendc(buf, '');
}
休憩。
デフォルト: //一直到这里、没特殊字符就会把值appendtobuf中
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)]);
私たち>>= 4;
smart_str_appendc(buf、digits [us&((1<< 4)-1)]);
私たち>>= 4;
smart_str_appendc(buf、digits [us&((1<< 4)-1)]);
私たち>>= 4;
smart_str_appendc(buf、digits [us&((1<< 4)-1)]);
}
休憩。
}
}
smart_str_appendc(buf, '"'); // 二重引き号を終了します。
efree(utf16);
}
再来看看数组和对象,また很简单,
static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC) /* {{{ */
{
int i, r;
ハッシュテーブル *myht;
if (Z_TYPE_PP(val) == IS_ARRAY) {
myht = HASH_OF(*val);
r = (オプション & 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, "再帰が検出されました");
smart_str_appendl(buf, "null", 4);
戻る;
}
//开始标签
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 **データ;
ulong インデックス。
uint key_len;
HashPosition pos;
ハッシュテーブル *tmp_ht;
int need_comma = 0;
zend_hash_internal_pointer_reset_ex(myht, &pos);
//便利哈希表
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)
休憩。
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;
}
//将值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] == ' ' && Z_TYPE_PP(val) == IS_OBJECT) {
/* 保護されたメンバーと非公開メンバーをスキップします。 */
if(tmp_ht){
tmp_ht->nApplyCount--;
}
続けます。
}
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_appendc(buf, '"');
Smart_str_appendc(buf, ':');
php_json_encode(buf, *data, options TSRMLS_CC);
}
}
}
}
//終了タグ
if (r == PHP_JSON_OUTPUT_ARRAY) {
smart_str_appendc(buf, ']');
} else {
smart_str_appendc(buf, '}');
}
}
簡単な分析を通じて、問題は実際には上記の sprintf を使用した方法と同じであることが証明されました。つまり、文字列を結合します。
http://www.bkjia.com/PHPjc/477721.html
www.bkjia.com
true
http://www.bkjia.com/PHPjc/477721.html技術記事 json の利点については話しません。私は json を出力するときに sprintf を使用して json 形式に変換するのが好きです。2 日前、私の友人はそれが標準ではないと言っていました。 json_encode によって標準化されます...