【原创】JSON格式编码操作类
可以使大家加深对字符串编码和json编码原理的了解
define('IS_NULL', 'NULL');
define('IS_BOOL', 'boolean');
define('IS_INT', 'integer');
define('IS_DOUBLE', 'double');
define('IS_STRING', 'string');
define('IS_ARRAY', 'array');
define('IS_OBJECT', 'object');
/**
* @author jiang kejun <jinhua_k9@163.com>
* @name Json
* @since 2013.6.3
* @uses 对json的操作
* @version $Id: json.php 376 2013.6.3 create jkj $
* @version $Id: json.php 385 2013.7.16 edit jkj $
*/
class Json
{
/**
* 转换介质对象
* @var string
*/
var $buf;
/**
* 存16进制unicode数组
* @var array
*/
var $utf16;
// =>
var $SIGN = ':';
// " key "
var $quotes = '"';
function __construct(){
$this->buf = "";
$this->utf16 = array();
}
/**
* 对utf8对象进行json格式编码
*
* @access public
* @param mixed $value
* @return string buf
*/
public function encode( $value ){
switch ( gettype( $value ) )
{
case IS_NULL:
$this->__S( $buf, "null" );
break;
case IS_BOOL:
$add = !empty( $value ) ? "true" : "false";
$this->__S( $this->buf, $add );
break;
case IS_INT:
$this->__S( $this->buf, (int)$value );
break;
case IS_DOUBLE:
$this->__S( $this->buf, (float)$value );
break;
case IS_STRING:
$this->_handle_string( $this->buf, $value );
break;
case IS_ARRAY:
$this->_handle_array( $this->buf, $value );
break;
case IS_OBJECT:
break;
default:
$this->__S( $this->buf, "null" );
break;
}
return $this->buf;
}
/**
* 处理数组
*
* @access private
* @param string &$buf
* @param array $data
*/
private function _handle_array( &$buf, array $data ) {
$count = count( $data );
$pos = 0;
//$iskey = isset( $data[0] );
$iskey = key($data);
if( !$iskey ){
$this->__S( $buf, '[' );
} else {
$this->__S( $buf, '{' );
}
foreach ( $data as $key=>$val ){
if( $iskey ){
$this->_handle_string( $buf, $key );
$this->__S( $buf, $this->SIGN );
}
$this->encode( $val );
if( $pos < $count-1 ) $this->__S( $buf, ',' );
$pos++;
}
if( !$iskey ){
$this->__S( $buf, ']' );
} else {
$this->__S( $buf, '}' );
}
}
/**
* 处理字符串
*
* @access private
* @param string &$buf
* @param string $s
*/
private function _handle_string( &$buf, $s ) {
$digits = array('0','1','2','3','4','5','6','7','8',
'9','a','b','c','d','e','f');
$len = strlen( $s );
if( $len == 0 ) {
$this->__S( $buf, "\"\"" );
}
$len = $this->utf8_to_utf16( $s );
if( $len <= 0 ){
if( $len < 0 ){
$this->__S( $buf, "null" );
} else {
$this->__S( $buf, "\"\"" );
}
return ;
}
$this->__S( $buf, $this->quotes );
if( is_numeric( $s ) ){
// double
if( strpos( $s, "." ) === false ){
$this->__S( $buf, (int)$s );
}
else {
$this->__S( $buf, (float)$s );
}
$len = 0;
}
$pos = 0;
while ( $pos < $len ) {
$us = $this->utf16[$pos++];
switch( $us )
{
case '"':
$this->__S( $buf, "\\\"" );
break;
case '\\':
$this->__S( $buf, "\\\\" );
break;
case '/':
$this->__S( $buf, "\\/" );
break;
case '\b':
$this->__S( $buf, "\\b" );
break;
case '\f':
$this->__S( $buf, "\\f" );
break;
case '\n':
$this->__S( $buf, "\\n" );
break;
case '\r':
$this->__S( $buf, "\\r" );
break;
case '\t':
$this->__S( $buf, "\\t" );
break;
case '<':
$this->__S( $buf, '<' );
break;
case '>':
$this->__S( $buf, '>' );
break;
case '&':
$this->__S( $buf, '&' );
break;
case '\'':
$this->__S( $buf, '\'' );
break;
default:
if ( $us >= ' ' && ( $us & 127 ) == $us ) {
$this->__S( $buf, $us );
} else {
$this->__S( $buf, "\\u" );
// 10进制转16进制
$this->__S( $buf, $digits[($us & 0xf000) >> 12] );
$this->__S( $buf, $digits[($us & 0xf00) >> 8] );
$this->__S( $buf, $digits[($us & 0xf0) >> 4] );
$this->__S( $buf, $digits[($us & 0xf)] );
}
break;
}
}
$this->__S( $buf, $this->quotes );
if ( $this->utf16 ){
$this->utf16 = array();
}
}
function __S( &$buf, $val ) {
if( NULL === $buf ) {
$buf = $val;
}
$buf .= $val;
}
/**
* 将utf8的unicode 转化成16进制的数组
*
* @param string $s
* @return int 数组的count
*/
function utf8_to_utf16( $s ) {
if( !$this->is_utf8( $s ) ){ return -1; }
$pos = 0;
$len = strlen( $s );
for( ;$pos < $len; ){
$ascii = ord( $s{$pos} );
if($ascii > 128)
{
$this->utf16[] = $this->_utf8_to_unicode( substr( $s, $pos, 3 ) );
$pos += 3;
}
else {
$this->utf16[] = $s{$pos};
$pos += 1;
}
}
return count( $this->utf16 );
}
/**
* 将16进制的数组转化成带utf8字符
*
* @param string $out_charset 返回的字符集编码,用于本地化和测试
* @return null|string str 带utf8字符
*/
function utf16_to_utf8( $out_charset='utf-8' ) {
if( !$this->utf16 ){ return null; }
$arr = array();
foreach ( $this->utf16 as $utf16 ) {
if( $utf16 > 0x80 || is_numeric( $utf16 ) )
{
$tmp = $this->_unicode_to_utf8( $utf16 );
if( !$this->is_utf8( $tmp ) )
$arr[] = chr(0);
else {
if( strtolower( $out_charset ) != 'utf-8' )
{
$arr[] = iconv( 'utf-8', $out_charset, $tmp );
}
else $arr[] = $tmp;
}
}
else {
$arr[] = $utf16;
}
}
return implode( "", $arr );
}
/**
* utf8转Unicode 10进制
*
* @param string $c
* @return int $un unicode
*/
function _utf8_to_unicode( $c ) {
$un = 0;
switch( strlen( $c ) ) {
case 1:
$un = ord( $c );
break;
case 2:
$un = ( ord( $c[0] ) & 0x3f ) << 6;
$un += ord( $c[1] ) & 0x3f;
break;
case 3:
$un = ( ord( $c[0] ) & 0x1f ) << 12;
$un += ( ord( $c[1] ) & 0x3f ) << 6;
$un += ord( $c[2] ) & 0x3f;
break;
case 4:
$un = ( ord( $c[0] ) & 0x0f ) << 18;
$un += ( ord( $c[1] ) & 0x3f ) << 12;
$un += ( ord( $c[2] ) & 0x3f ) << 6;
$un += ord( $c[3] ) & 0x3f;
break;
}
return $un;
}
/**
* 10进制unicode转utf8
*
* @param int $un
* @return string utf8编码字符
*/
function _unicode_to_utf8( $un ) {
$c1 = 0; $c2 = 0;
$c3 = 0; $c4 = 0;
if( $un < 0x80 )
$c1 = $un >> 0 & 0x7F | 0x00;
elseif( $un < 0x0800 ){
$c1 = $un >> 6 & 0x1F | 0xC0;
$c2 = $un >> 0 & 0x3F | 0x80;
}
elseif( $un < 0x010000 ){
$c1 = $un >> 12 & 0x0F | 0xE0;
$c2 = $un >> 6 & 0x3F | 0x80;
$c3 = $un >> 0 & 0x3F | 0x80;
}
elseif( $un < 0x110000 ){
$c1 = $un >> 18 & 0x07 | 0xF0;
$c2 = $un >> 12 & 0x3F | 0x80;
$c3 = $un >> 6 & 0x3F | 0x80;
$c4 = $un >> 0 & 0x3F | 0x80;
}
return chr( $c1 ).chr( $c2 ).
chr( $c3 ).chr( $c4 );
}
/**
* 是否是utf8编码字符串
*
* @param string $str
* @return bool
*/
function is_utf8( $str ) {
$c = 0; $b = 0;
$bits = 0;
$len = strlen( $str );
for( $i = 0; $i < $len; $i++ ){
$c = ord( $str[$i] );
if( $c > 128 ){
if( $c >= 254 ) return false;
elseif( $c >= 252 ) $bits = 6;
elseif( $c >= 248 ) $bits = 5;
elseif( $c >= 240 ) $bits = 4;
elseif( $c >= 224 ) $bits = 3;
elseif( $c >= 192 ) $bits = 2;
else return false;
if( ( $i + $bits ) > $len ) return false;
while( $bits > 1 ){
$i++;
$b = ord( $str[$i] );
if( $b < 128 || $b > 191 ) return false;
$bits--;
}
}
}
return true;
}
/**
* 对 JSON 格式的字符串进行解码
*
* @access public
* @param string $json
* @param bool $assoc true:返回array; false:返回stdclass
* @return mixed
*/
public function decode( $json, $assoc=false ) {
############################################
## Is interested to continue to write ##
## use methods have already been written ##
## Began to write in here ##
############################################
return $mixed;
}
}