解决json_encode中文会编码为unicode,兼容php5.4之前的版本

解决json_encode中文会编码为unicode,兼容php5.4之前的版本

编码后也可以正确的用json_decode进行解码

1、使用正则

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
 * 解决json_encode的中文兼容问题(虽然看似兼容5.2不过没测试过)
 *
 * @param  array|stdClass $value 被编码的数据
 *
 * @return 编码为json字符串的数据
 */
function json_encode_unescaped_unicode($value)
{
    static $callback;

    if (version_compare(PHP_VERSION, '5.4.0', '<')) {
        if (!is_callable($callback)) {
            $callback = create_function('$matchs',
                'return iconv(\'UCS-2BE\', \'UTF-8\', pack(\'H4\', $matchs[1]));'
            );
        }

        $str = json_encode($value);
        $str = preg_replace_callback("#\\\u([0-9a-f]{4})#i", $callback, $str);

        return $str;
    } else {
        return json_encode($value, JSON_UNESCAPED_UNICODE);
    }
}

性能测试(环境:MACBOOKPRO 13 2015款)

代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<?php

////////////////////////////////////////////////////////////////
/// 解决 5.4以下的encode中文没有 JSON_UNESCAPED_UNICODE 选项的问题
////////////////////////////////////////////////////////////////

$num = 0;
$count = 0;
$time = microtime(true);

function my_log()
{
    global $count, $time, $num;

    if (microtime(true) - $time >= 1) {
        printf("次数:%d\n", $count);

        $count = 0;
        $time = microtime(true);
        $num++;
    }
}

register_tick_function('my_log');

/**
 * 解决json_encode的中文兼容问题(虽然看似兼容5.2不过没测试过)
 *
 * @param  array|stdClass $value 被编码的数据
 *
 * @return 编码为json字符串的数据
 */
function json_encode_unescaped_unicode($value)
{
    static $callback;

    if (version_compare(PHP_VERSION, '5.4.0', '<')) {
        if (!is_callable($callback)) {
            $callback = create_function('$matchs',
                'return iconv(\'UCS-2BE\', \'UTF-8\', pack(\'H4\', $matchs[1]));'
            );
        }

        $str = json_encode($value);
        $str = preg_replace_callback("#\\\u([0-9a-f]{4})#i", $callback, $str);

        return $str;
    } else {
        return json_encode($value, JSON_UNESCAPED_UNICODE);
    }
}

$data = array(
    'qwe' => '你好世界',
    'asd' => array(
        '神奇了',
        'zxc' => array(
            's' => '那么再深一点'
        )
    )
);

declare(ticks = 1)
{
    while ($num < 10) {
        json_encode_unescaped_unicode($data);
        $count++;
    }
}

php5.3:(每秒encode次数)

次数:39405

次数:39829

次数:40229

次数:40300

次数:40425

次数:41298

次数:38226

次数:40405

次数:40758

次数:39853

php5.6:(每秒encode次数)

次数:380351

次数:376383

次数:384623

次数:385797

次数:381795

次数:374920

次数:366855

次数:380634

次数:373909

次数:379061

性能上的差异肯定是有的毕竟又用正则又用iconv的。

从测试上看,9倍左右的差距应该还包含php5.6本身就比5.3快的原因。

不过这个差距是有点大,那么还是赶紧升级php5.6吧,现在的大趋势都是7.1了,还在用老款干啥呀,各种新特性高性能在等着各位phper!(跑题了)

2、先用urlencode编码中文,在json_encode之后再用urldecode转换回来

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
function json_encode_unescaped_unicode($value, $is_deep = false)
{
    if (version_compare(PHP_VERSION, '5.4.0', '<')) {
        foreach ($value as $k => &$v) {
            if (is_string($v)) {
                $v = urlencode($v);
            } else if (is_array($v)) {
                $v = json_encode_unescaped_unicode($v, true);
            }
        }

        return $is_deep ? $value : urldecode(json_encode($value));
    } else {
        return json_encode($value, JSON_UNESCAPED_UNICODE);
    }
}

同样的测试,这个性能没高多少,而且还带着个递归

php5.3:

次数:72744

次数:72718

次数:74101

次数:75071

次数:75672

次数:73354

次数:75474

次数:73025

次数:74453

次数:75715

原创文章转载请注明出处哟!

Licensed under CC BY-NC-SA 4.0