org.zodiac.sdk.json.to.JSONToHandler 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.to;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Iterator;
import org.zodiac.sdk.json.JSONNode;
import org.zodiac.sdk.json.JSONNodeData;
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.core.JSONOptions;
import org.zodiac.sdk.json.ext.ThreadLocalData;
public class JSONToHandler implements ToHandler {
private static final ThreadLocalData tlBuilder = new ThreadLocalData<>(() -> new StringBuilder(1024 * 5));
@Override
public void handle(JSONContext ctx) {
JSONNode o = (JSONNode)ctx.source;
if (null != o) {
StringBuilder sb = tlBuilder.get(); // new StringBuilder(1024*5); //
sb.setLength(0);
analyse(ctx.options, o, sb);
ctx.target = sb.toString();
}
}
public void analyse(JSONOptions opts, JSONNode o, StringBuilder sb) {
if (o == null) {
return;
}
switch (o.nodeType()) {
case Value:
writeValue(opts, sb, o.nodeData());
break;
case Array:
writeArray(opts, sb, o.nodeData());
break;
case Object:
writeObject(opts, sb, o.nodeData());
break;
default:
sb.append("null");
break;
}
}
private void writeArray(JSONOptions opts, StringBuilder sBuf, JSONNodeData d) {
sBuf.append("[");
Iterator iterator = d.array.iterator();
while (iterator.hasNext()) {
JSONNode sub = iterator.next();
analyse(opts, sub, sBuf);
if (iterator.hasNext()) {
sBuf.append(",");
}
}
sBuf.append("]");
}
private void writeObject(JSONOptions opts, StringBuilder sBuf, JSONNodeData d) {
sBuf.append("{");
Iterator itr = d.object.keySet().iterator();
while (itr.hasNext()) {
String k = itr.next();
writeName(opts, sBuf, k);
sBuf.append(":");
analyse(opts, d.object.get(k), sBuf);
if (itr.hasNext()) {
sBuf.append(",");
}
}
sBuf.append("}");
}
private void writeValue(JSONOptions opts, StringBuilder sBuf, JSONNodeData d) {
JSONValue v = d.value;
switch (v.type()) {
case Null:
sBuf.append("null");
break;
case String:
writeValString(opts, sBuf, v.getRawString(), true);
break;
case DateTime:
writeValDate(opts, sBuf, v.getRawDate());
break;
case Boolean:
writeValBool(opts, sBuf, v.getRawBoolean());
break;
case Number:
writeValNumber(opts, sBuf, v.getRawNumber());
break;
default:
sBuf.append(v.getString());
break;
}
}
private void writeName(JSONOptions opts, StringBuilder sBuf, String val) {
if (opts.hasFeature(Feature.QuoteFieldNames)) {
if (opts.hasFeature(Feature.UseSingleQuotes)) {
sBuf.append("'").append(val).append("'");
} else {
sBuf.append("\"").append(val).append("\"");
}
} else {
sBuf.append(val);
}
}
private void writeValDate(JSONOptions opts, StringBuilder sBuf, Date val) {
if (opts.hasFeature(Feature.WriteDateUseTicks)) {
sBuf.append(val.getTime());
} else if (opts.hasFeature(Feature.WriteDateUseFormat)) {
writeValString(opts, sBuf, opts.dateToString(val), false);
} else {
sBuf.append("new Date(").append(val.getTime()).append(")");
}
}
private void writeValBool(JSONOptions opts, StringBuilder sBuf, Boolean val) {
if (opts.hasFeature(Feature.WriteBoolUse01)) {
sBuf.append(val ? 1 : 0);
} else {
sBuf.append(val ? "true" : "false");
}
}
private void writeValNumber(JSONOptions opts, StringBuilder sBuf, Number val) {
if (val instanceof BigInteger) {
BigInteger v = (BigInteger)val;
String sVal = v.toString();
if (opts.hasFeature(Feature.WriteNumberUseString)) {
writeValString(opts, sBuf, sVal, false);
} else {
// 数字太大时,可用string来表示;
if (sVal.length() > 16 && (v.compareTo(JSONConstants.INT_LOW) < 0 || v.compareTo(JSONConstants.INT_HIGH) > 0)
&& opts.hasFeature(Feature.BrowserCompatible)) {
writeValString(opts, sBuf, sVal, false);
} else {
sBuf.append(sVal);
}
}
return;
}
if (val instanceof BigDecimal) {
BigDecimal v = (BigDecimal)val;
String sVal = v.toPlainString();
if (opts.hasFeature(Feature.WriteNumberUseString)) {
writeValString(opts, sBuf, sVal, false);
} else {
// 数字太大时,可用string来表示;
if (sVal.length() > 16 && (v.compareTo(JSONConstants.DEC_LOW) < 0 || v.compareTo(JSONConstants.DEC_HIGH) > 0)
&& opts.hasFeature(Feature.BrowserCompatible)) {
writeValString(opts, sBuf, sVal, false);
} else {
sBuf.append(sVal);
}
}
return;
}
if (opts.hasFeature(Feature.WriteNumberUseString)) {
writeValString(opts, sBuf, val.toString(), false);
} else {
sBuf.append(val.toString());
}
}
private void writeValString(JSONOptions opts, StringBuilder sBuf, String val, boolean isStr) {
// 引号开始
boolean useSingleQuotes = opts.hasFeature(Feature.UseSingleQuotes);
char quote = (useSingleQuotes ? '\'' : '\"');
sBuf.append(quote);
// 内容
if (isStr) {
boolean isCompatible = opts.hasFeature(Feature.BrowserCompatible);
boolean isSecure = opts.hasFeature(Feature.BrowserSecure);
for (int i = 0, len = val.length(); i < len; i++) {
char c = val.charAt(i);
// 引号转义处理 + 特殊字符必须码
if (c == quote || c == '\\' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\b'
|| (c >= '\0' && c <= '\7')) {
sBuf.append("\\");
sBuf.append(JSONConstants.CHARS_MARK[(int)c]);
continue;
}
if (isSecure) {
if (c == '(' || c == ')' || c == '<' || c == '>') {
sBuf.append('\\');
sBuf.append('u');
sBuf.append(JSONConstants.DIGITS[(c >>> 12) & 15]);
sBuf.append(JSONConstants.DIGITS[(c >>> 8) & 15]);
sBuf.append(JSONConstants.DIGITS[(c >>> 4) & 15]);
sBuf.append(JSONConstants.DIGITS[c & 15]);
continue;
}
}
if (isCompatible) {
// 对不可见ASC码,进行编码处理
if (c < 32) {
sBuf.append('\\');
sBuf.append('u');
sBuf.append('0');
sBuf.append('0');
sBuf.append(JSONConstants.DIGITS[(c >>> 4) & 15]);
sBuf.append(JSONConstants.DIGITS[c & 15]);
continue;
}
// 对大码,进行编码处理
if (c >= 127) {
sBuf.append('\\');
sBuf.append('u');
sBuf.append(JSONConstants.DIGITS[(c >>> 12) & 15]);
sBuf.append(JSONConstants.DIGITS[(c >>> 8) & 15]);
sBuf.append(JSONConstants.DIGITS[(c >>> 4) & 15]);
sBuf.append(JSONConstants.DIGITS[c & 15]);
continue;
}
}
sBuf.append(c);
}
} else {
// 非字符串直接添加
sBuf.append(val);
}
// 引号结束
sBuf.append(quote);
}
}