All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zodiac.sdk.json.to.JSONToHandler Maven / Gradle / Ivy

There is a newer version: 1.5.17
Show newest version
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);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy