From 609162e030aca61c311129e9f3a6083e5e6dd30f Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 30 Sep 2022 23:36:55 +0800 Subject: [PATCH] add writer --- .../json/writer/BooleanValueWriter.java | 19 ++ .../hutool/json/writer/DateValueWriter.java | 26 +++ .../json/writer/JSONStringValueWriter.java | 45 ++++ .../hutool/json/writer/JSONValueWriter.java | 19 ++ .../cn/hutool/json/writer/JSONWriter.java | 207 +++++++----------- .../hutool/json/writer/NumberValueWriter.java | 33 +++ 6 files changed, 225 insertions(+), 124 deletions(-) create mode 100755 hutool-json/src/main/java/cn/hutool/json/writer/BooleanValueWriter.java create mode 100755 hutool-json/src/main/java/cn/hutool/json/writer/DateValueWriter.java create mode 100755 hutool-json/src/main/java/cn/hutool/json/writer/JSONStringValueWriter.java create mode 100755 hutool-json/src/main/java/cn/hutool/json/writer/JSONValueWriter.java create mode 100755 hutool-json/src/main/java/cn/hutool/json/writer/NumberValueWriter.java diff --git a/hutool-json/src/main/java/cn/hutool/json/writer/BooleanValueWriter.java b/hutool-json/src/main/java/cn/hutool/json/writer/BooleanValueWriter.java new file mode 100755 index 000000000..04cb1b081 --- /dev/null +++ b/hutool-json/src/main/java/cn/hutool/json/writer/BooleanValueWriter.java @@ -0,0 +1,19 @@ +package cn.hutool.json.writer; + +/** + * Boolean类型的值写出器 + * + * @author looly + * @since 6.0.0 + */ +public class BooleanValueWriter implements JSONValueWriter { + /** + * 单例对象 + */ + public static final BooleanValueWriter INSTANCE = new BooleanValueWriter(); + + @Override + public void write(final JSONWriter writer, final Boolean bool) { + writer.writeRaw(bool.toString()); + } +} diff --git a/hutool-json/src/main/java/cn/hutool/json/writer/DateValueWriter.java b/hutool-json/src/main/java/cn/hutool/json/writer/DateValueWriter.java new file mode 100755 index 000000000..20c36c6df --- /dev/null +++ b/hutool-json/src/main/java/cn/hutool/json/writer/DateValueWriter.java @@ -0,0 +1,26 @@ +package cn.hutool.json.writer; + +import cn.hutool.json.serialize.DateJSONString; + +import java.time.temporal.TemporalAccessor; +import java.util.Calendar; +import java.util.Date; + +/** + * 日期类型的值写出器
+ * 支持包括:{@link Date}、{@link Calendar}、{@link TemporalAccessor} + * + * @author looly + * @since 6.0.0 + */ +public class DateValueWriter implements JSONValueWriter { + /** + * 单例对象 + */ + public static final DateValueWriter INSTANCE = new DateValueWriter(); + + @Override + public void write(final JSONWriter writer, final Object value) { + writer.writeRaw(new DateJSONString(value, writer.getConfig()).toJSONString()); + } +} diff --git a/hutool-json/src/main/java/cn/hutool/json/writer/JSONStringValueWriter.java b/hutool-json/src/main/java/cn/hutool/json/writer/JSONStringValueWriter.java new file mode 100755 index 000000000..dab0aa9fb --- /dev/null +++ b/hutool-json/src/main/java/cn/hutool/json/writer/JSONStringValueWriter.java @@ -0,0 +1,45 @@ +package cn.hutool.json.writer; + +import cn.hutool.json.JSONException; +import cn.hutool.json.serialize.JSONString; + +import java.time.temporal.TemporalAccessor; +import java.util.Calendar; +import java.util.Date; + +/** + * 日期类型的值写出器
+ * 支持包括:{@link Date}、{@link Calendar}、{@link TemporalAccessor} + * + * @author looly + * @since 6.0.0 + */ +public class JSONStringValueWriter implements JSONValueWriter { + /** + * 单例对象 + */ + public static final JSONStringValueWriter INSTANCE = new JSONStringValueWriter(); + + /** + * 输出实现了{@link JSONString}接口的对象,通过调用{@link JSONString#toJSONString()}获取JSON字符串
+ * {@link JSONString}按照JSON对象对待,此方法输出的JSON字符串不包装引号。
+ * 如果toJSONString()返回null,调用toString()方法并使用双引号包装。 + * + * @param writer {@link JSONWriter} + * @param jsonString {@link JSONString} + */ + @Override + public void write(final JSONWriter writer, final JSONString jsonString) { + final String valueStr; + try { + valueStr = jsonString.toJSONString(); + } catch (final Exception e) { + throw new JSONException(e); + } + if (null != valueStr) { + writer.writeRaw(valueStr); + } else { + writer.writeQuoteStrValue(jsonString.toString()); + } + } +} diff --git a/hutool-json/src/main/java/cn/hutool/json/writer/JSONValueWriter.java b/hutool-json/src/main/java/cn/hutool/json/writer/JSONValueWriter.java new file mode 100755 index 000000000..cd3c7b722 --- /dev/null +++ b/hutool-json/src/main/java/cn/hutool/json/writer/JSONValueWriter.java @@ -0,0 +1,19 @@ +package cn.hutool.json.writer; + +/** + * JSON的值自定义写出 + * + * @param 写出的对象类型 + * @author looly + * @since 6.0.0 + */ +public interface JSONValueWriter { + + /** + * 使用{@link JSONWriter} 写出对象 + * + * @param writer {@link JSONWriter} + * @param value 被写出的值 + */ + void write(JSONWriter writer, T value); +} diff --git a/hutool-json/src/main/java/cn/hutool/json/writer/JSONWriter.java b/hutool-json/src/main/java/cn/hutool/json/writer/JSONWriter.java index 42d40e502..d6e1e93c5 100755 --- a/hutool-json/src/main/java/cn/hutool/json/writer/JSONWriter.java +++ b/hutool-json/src/main/java/cn/hutool/json/writer/JSONWriter.java @@ -2,14 +2,11 @@ package cn.hutool.json.writer; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.lang.mutable.MutableEntry; -import cn.hutool.core.math.NumberUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.CharUtil; import cn.hutool.json.InternalJSONUtil; import cn.hutool.json.JSON; import cn.hutool.json.JSONConfig; -import cn.hutool.json.JSONException; -import cn.hutool.json.serialize.DateJSONString; import cn.hutool.json.serialize.JSONString; import java.io.IOException; @@ -82,6 +79,15 @@ public class JSONWriter extends Writer { this.config = config; } + /** + * 获取JSON配置 + * + * @return {@link JSONConfig} + */ + public JSONConfig getConfig() { + return this.config; + } + /** * JSONObject写出开始,默认写出"{" * @@ -145,7 +151,7 @@ public class JSONWriter extends Writer { } } - if(false == arrayMode){ + if (false == arrayMode) { // JSONObject模式,写出键,否则只输出值 writeKey(StrUtil.toString(pair.getKey())); } @@ -190,6 +196,75 @@ public class JSONWriter extends Writer { this.writer.close(); } + /** + * 写出字符串值,并包装引号并转义字符
+ * 对所有双引号做转义处理(使用双反斜杠做转义)
+ * 为了能在HTML中较好的显示,会将</转义为<\/
+ * JSON字符串中不能包含控制字符和未经转义的引号和反斜杠 + * + * @param csq 字符串 + */ + public void writeQuoteStrValue(final String csq) { + InternalJSONUtil.quote(csq, writer); + } + + /** + * 写出空格 + * + * @param count 空格数 + */ + public void writeSpace(final int count) { + if (indentFactor > 0) { + for (int i = 0; i < count; i++) { + //noinspection resource + writeRaw(CharUtil.SPACE); + } + } + } + + /** + * 写出换换行符 + * + * @return this + */ + public JSONWriter writeLF() { + if (indentFactor > 0) { + //noinspection resource + writeRaw(CharUtil.LF); + } + return this; + } + + /** + * 写入原始字符串值,不做任何处理 + * + * @param csq 字符串 + * @return this + */ + public JSONWriter writeRaw(final String csq) { + try { + writer.append(csq); + } catch (final IOException e) { + throw new IORuntimeException(e); + } + return this; + } + + /** + * 写入原始字符值,不做任何处理 + * + * @param c 字符串 + * @return this + */ + public JSONWriter writeRaw(final char c) { + try { + writer.write(c); + } catch (final IOException e) { + throw new IORuntimeException(e); + } + return this; + } + // ------------------------------------------------------------------------------ Private methods /** @@ -231,133 +306,17 @@ public class JSONWriter extends Writer { } else if (value instanceof JSON) { ((JSON) value).write(writer, indentFactor, indent, predicate); } else if (value instanceof Number) { - writeNumberValue((Number) value); + NumberValueWriter.INSTANCE.write(this, (Number) value); } else if (value instanceof Date || value instanceof Calendar || value instanceof TemporalAccessor) { - //noinspection resource - writeRaw(new DateJSONString(value, config).toJSONString()); + DateValueWriter.INSTANCE.write(this, value); } else if (value instanceof Boolean) { - writeBooleanValue((Boolean) value); + BooleanValueWriter.INSTANCE.write(this, (Boolean) value); } else if (value instanceof JSONString) { - writeJSONStringValue((JSONString) value); + JSONStringValueWriter.INSTANCE.write(this, (JSONString) value); } else { writeQuoteStrValue(value.toString()); } return this; } - - /** - * 写出数字,根据{@link JSONConfig#isStripTrailingZeros()} 配置不同,写出不同数字
- * 主要针对Double型是否去掉小数点后多余的0
- * 此方法输出的值不包装引号。 - * - * @param number 数字 - */ - private void writeNumberValue(final Number number) { - // since 5.6.2可配置是否去除末尾多余0,例如如果为true,5.0返回5 - final boolean isStripTrailingZeros = null == config || config.isStripTrailingZeros(); - //noinspection resource - writeRaw(NumberUtil.toStr(number, isStripTrailingZeros)); - } - - /** - * 写出Boolean值,直接写出true或false,不适用引号包装 - * - * @param value Boolean值 - */ - private void writeBooleanValue(final Boolean value) { - //noinspection resource - writeRaw(value.toString()); - } - - /** - * 输出实现了{@link JSONString}接口的对象,通过调用{@link JSONString#toJSONString()}获取JSON字符串
- * {@link JSONString}按照JSON对象对待,此方法输出的JSON字符串不包装引号。
- * 如果toJSONString()返回null,调用toString()方法并使用双引号包装。 - * - * @param jsonString {@link JSONString} - */ - private void writeJSONStringValue(final JSONString jsonString) { - final String valueStr; - try { - valueStr = jsonString.toJSONString(); - } catch (final Exception e) { - throw new JSONException(e); - } - if (null != valueStr) { - //noinspection resource - writeRaw(valueStr); - } else { - writeQuoteStrValue(jsonString.toString()); - } - } - - /** - * 写出字符串值,并包装引号并转义字符
- * 对所有双引号做转义处理(使用双反斜杠做转义)
- * 为了能在HTML中较好的显示,会将</转义为<\/
- * JSON字符串中不能包含控制字符和未经转义的引号和反斜杠 - * - * @param csq 字符串 - */ - private void writeQuoteStrValue(final String csq) { - InternalJSONUtil.quote(csq, writer); - } - - /** - * 写出空格 - * - * @param count 空格数 - */ - private void writeSpace(final int count) { - if (indentFactor > 0) { - for (int i = 0; i < count; i++) { - //noinspection resource - writeRaw(CharUtil.SPACE); - } - } - } - - /** - * 写出换换行符 - * - * @return this - */ - private JSONWriter writeLF() { - if (indentFactor > 0) { - //noinspection resource - writeRaw(CharUtil.LF); - } - return this; - } - - /** - * 写入原始字符串值,不做任何处理 - * - * @param csq 字符串 - * @return this - */ - private JSONWriter writeRaw(final String csq) { - try { - writer.append(csq); - } catch (final IOException e) { - throw new IORuntimeException(e); - } - return this; - } - - /** - * 写入原始字符值,不做任何处理 - * - * @param c 字符串 - * @return this - */ - private JSONWriter writeRaw(final char c) { - try { - writer.write(c); - } catch (final IOException e) { - throw new IORuntimeException(e); - } - return this; - } } diff --git a/hutool-json/src/main/java/cn/hutool/json/writer/NumberValueWriter.java b/hutool-json/src/main/java/cn/hutool/json/writer/NumberValueWriter.java new file mode 100755 index 000000000..3f4f94886 --- /dev/null +++ b/hutool-json/src/main/java/cn/hutool/json/writer/NumberValueWriter.java @@ -0,0 +1,33 @@ +package cn.hutool.json.writer; + +import cn.hutool.core.math.NumberUtil; +import cn.hutool.json.JSONConfig; + +/** + * 数字类型的值写出器 + * + * @author looly + * @since 6.0.0 + */ +public class NumberValueWriter implements JSONValueWriter { + /** + * 单例对象 + */ + public static final NumberValueWriter INSTANCE = new NumberValueWriter(); + + /** + * 写出数字,根据{@link JSONConfig#isStripTrailingZeros()} 配置不同,写出不同数字
+ * 主要针对Double型是否去掉小数点后多余的0
+ * 此方法输出的值不包装引号。 + * + * @param writer {@link JSONWriter} + * @param number 数字 + */ + @Override + public void write(final JSONWriter writer, final Number number) { + final JSONConfig config = writer.getConfig(); + // since 5.6.2可配置是否去除末尾多余0,例如如果为true,5.0返回5 + final boolean isStripTrailingZeros = null == config || config.isStripTrailingZeros(); + writer.writeRaw(NumberUtil.toStr(number, isStripTrailingZeros)); + } +}