org.zodiac.sdk.json.from.JSONFromHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of zodiac-sdk-json Show documentation
Show all versions of zodiac-sdk-json Show documentation
Zodiac SDK JSON(JavaScript Object Notation)
package org.zodiac.sdk.json.from;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import org.zodiac.sdk.json.CharBuffer;
import org.zodiac.sdk.json.CharReader;
import org.zodiac.sdk.json.JSONNode;
import org.zodiac.sdk.json.JSONValue;
import org.zodiac.sdk.json.constants.JSONConstants;
import org.zodiac.sdk.json.core.Feature;
import org.zodiac.sdk.json.core.JSONContext;
import org.zodiac.sdk.json.exception.JSONException;
import org.zodiac.sdk.json.ext.ThreadLocalData;
/**
* Json 解析器(将 json string 转为 JSONNode)。
* key:支持双引号、单引号、无引号。
* str:支持双引号、单引号。
*/
public class JSONFromHandler implements FromHandler {
private static final ThreadLocalData tlBuilder = new ThreadLocalData<>(()->new CharBuffer());
public JSONFromHandler() {
super();
}
@Override
public void handle(JSONContext ctx) throws IOException {
ctx.target = do_handle(ctx, (String) ctx.source);
}
private JSONNode do_handle(JSONContext ctx, String text) throws IOException {
if (text == null) {
return new JSONNode(ctx.options);
} else {
text = text.trim();//去除两边的空隔
}
int len = text.length();
JSONNode node;
//完整的处理(支持像:"xx",'xx',12,true,{...},[],null,undefined 等)
//
if (len == 0) {
node = new JSONNode(ctx.options);
} else {
char prefix = text.charAt(0);
char suffix = text.charAt(text.length() - 1);
if ((prefix == '{' && suffix == '}')
|| (prefix == '[' && suffix == ']')) {
//object or array
//
CharBuffer sBuf = tlBuilder.get(); // new CharBuffer();//
sBuf.setLength(0);
node = new JSONNode(ctx.options);
analyse(ctx,new CharReader(text), sBuf, node);
} else if (len >= 2 && (
(prefix == '"' && suffix == '"') ||
(prefix == '\'' && suffix == '\''))) {
//string
//
node = analyse_val(ctx, text.substring(1, len - 1), true, false);
} else if (prefix != '<' && len < 40) {
//null,num,bool,other
//
node = analyse_val(ctx, text, false, true);
} else {
//普通的字符串
node = new JSONNode(ctx.options);
node.val().setString(text);
}
}
return node;
}
public void analyse(JSONContext ctx, CharReader sr, CharBuffer sBuf, JSONNode p) throws IOException {
String name = null;
boolean read_space1=false;
// 读入字符
while (sr.read()) {
char c = sr.value();
// 根据字符
switch (c) {
case '"':
scanString(sr, sBuf, '"');
if (analyse_buf(ctx, p, name, sBuf)) {
name = null;
}
break;
case '\'':
scanString(sr, sBuf, '\'');
if (analyse_buf(ctx, p, name, sBuf)) {
name = null;
}
break;
case '{':
if (p.isObject()) {
analyse(ctx, sr, sBuf, p.getNew(name).asObject());
name = null;
} else if (p.isArray()) {
analyse(ctx, sr, sBuf, p.addNew().asObject());
} else {
analyse(ctx, sr, sBuf, p.asObject());
}
break;
case '[':
if (p.isObject()) {
analyse(ctx, sr, sBuf, p.getNew(name).asArray());
name = null;
} else if (p.isArray()) {
analyse(ctx, sr, sBuf, p.addNew().asArray());
} else {
analyse(ctx, sr, sBuf, p.asArray());
}
break;
case ':':
// 新的键名
name = sBuf.toString();
sBuf.setLength(0);
break;
case ',':
if (sBuf.length() > 0) {
if (analyse_buf(ctx, p, name, sBuf)) {
name = null;
}
}
break;
case '}':
if (sBuf.length() > 0) {
analyse_buf(ctx, p, name, sBuf);//都返回了,不需要name=null了
}
return;
case ']':
if (sBuf.length() > 0) {
analyse_buf(ctx, p, name, sBuf);//都返回了,不需要name=null了
}
return;
default:
if (sBuf.length() == 0) { //支持:new Date(xxx) //当中有空隔
if (c > 32) {//无引号的,只添加可见字符(key,no string val)
sBuf.append(c);
if (c == 'n') { //如果是 n开头, 可以读一次空隔
read_space1 = true;
}
}
} else {
if (c > 32) {
sBuf.append(c);
} else if(c == 32){
if (read_space1) {
read_space1 = false;
sBuf.append(c);
}
}
}
break;
}
}
}
private boolean analyse_buf(JSONContext ctx,JSONNode p, String name, CharBuffer sBuf) {
if (p.isObject()) {
if (name != null) {
p.setNode(name, analyse_val(ctx, sBuf));
sBuf.setLength(0);
return true;
}
} else if (p.isArray()) {
p.addNode(analyse_val(ctx, sBuf));
sBuf.setLength(0);
}
return false;
}
private void scanString(CharReader sr, CharBuffer sBuf, char quote) throws IOException {
//没有包括引号,不需要删除动作
sBuf.isString = true;
while (sr.read()) {
char c = sr.value();
if (quote == c) {
return;
}
if ('\\' == c) {
c = sr.next();
if ('t' == c || 'r' == c || 'n' == c || 'f' == c || 'b' == c || '"' == c || '\'' == c || '/'==c || (c >= '0' && c <= '7')) {
sBuf.append(JSONConstants.CHARS_MARK_REV[(int) c]);
continue;
}
if ('x' == c) {
//16进制的处理。
char x1 = sr.next();
char x2 = sr.next();
int val = JSONConstants.DIGITS_MARK[x1] * 16 + JSONConstants.DIGITS_MARK[x2];
sBuf.append((char) val);
continue;
}
if ('u' == c) {
int val = 0;
//unicode的处理。对于码值大于0xFFFF的字符,仅支持\ud83d\udc4c这样4字节表示方法,不支持\u1f44c这样的两个半字节表示法
c = sr.next();
val = ((val << 4) + JSONConstants.DIGITS_MARK[c]); //Character.digit(c, 16)
c = sr.next();
val = ((val << 4) + JSONConstants.DIGITS_MARK[c]);
c = sr.next();
val = ((val << 4) + JSONConstants.DIGITS_MARK[c]);
c = sr.next();
val = ((val << 4) + JSONConstants.DIGITS_MARK[c]);
sBuf.append((char) val);
continue;
}
sBuf.append('\\');
sBuf.append(c);
} else {
sBuf.append(c);
}
}
}
private JSONNode analyse_val(JSONContext ctx,CharBuffer sBuf) {
if (sBuf.isString == false) {
sBuf.trimLast();//去掉尾部的空格
}
return analyse_val(ctx,sBuf.toString(), sBuf.isString, false);
}
private JSONNode analyse_val(JSONContext ctx,String sval, boolean isString, boolean isNoterr) {
JSONNode orst = null;
if (isString) {
if(ctx.options.hasFeature(Feature.StringJsonToNode)) {
if ((sval.startsWith("{") && sval.endsWith("}")) ||
(sval.startsWith("[") && sval.endsWith("]"))) {
orst = JSONNode.loadStr(sval, ctx.options);
}
}
if(orst == null){
orst = new JSONNode(ctx.options);
orst.val().setString(sval);
}
} else {
orst = new JSONNode(ctx.options);
JSONValue oval = orst.val();
char c = sval.charAt(0);
int len = sval.length();
if (c == 't' && len == 4) { //true
oval.setBool(true);
} else if (c == 'f' && len == 5) { //false
oval.setBool(false);
} else if (c == 'n') { // null or new (new not sup)
if (len == 4) {
oval.setNull();
} else if (sval.indexOf('D') == 4) { //new Date(xxx)
long ticks = Long.parseLong(sval.substring(9, sval.length() - 1));
oval.setDate(new Date(ticks));
}
} else if (c == 'N' && len == 3) { // NaN
oval.setNull();
} else if (c == 'u' && len == 9) { // undefined
oval.setNull();
} else if ((c >= '0' && c <= '9') || (c == '-')) { //number
if (sval.length() > 16) { //超过16位长度;采用大数字处理
if (sval.indexOf('.') > 0) {
oval.setNumber(new BigDecimal(sval));
} else {
oval.setNumber(new BigInteger(sval));
}
} else { //小于16位长度;采用常规数字处理
if (sval.indexOf('.') > 0 ) {
oval.setNumber(Double.parseDouble(sval));
} else {
oval.setNumber(Long.parseLong(sval));
}
}
} else { //other
if(isNoterr){
oval.setString(sval);
}else {
throw new JSONException("Format error!");
}
}
}
return orst;
}
}