From e4b7acf1670177ee0feb690dca11fc698db96593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Sch=C3=A4fer?= Date: Thu, 9 Aug 2018 08:45:15 +0200 Subject: [PATCH] Improve serializeJSON() This commit tries to improve serializeJSON() to get closer to rfc4627. It includes a more proper quoting of strings and output of integers instead of floats where appropriate. --- .../scriptengine/util/HostObjectUtil.java | 55 +++++++++++++++++-- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/components/script-engine/org.jaggeryjs.scriptengine/src/main/java/org/jaggeryjs/scriptengine/util/HostObjectUtil.java b/components/script-engine/org.jaggeryjs.scriptengine/src/main/java/org/jaggeryjs/scriptengine/util/HostObjectUtil.java index 89ff23e2..6bc22e24 100644 --- a/components/script-engine/org.jaggeryjs.scriptengine/src/main/java/org/jaggeryjs/scriptengine/util/HostObjectUtil.java +++ b/components/script-engine/org.jaggeryjs.scriptengine/src/main/java/org/jaggeryjs/scriptengine/util/HostObjectUtil.java @@ -24,6 +24,7 @@ import java.util.Date; import java.util.Map.Entry; import java.util.TimeZone; +import java.util.regex.Pattern; public class HostObjectUtil { @@ -32,6 +33,9 @@ public class HostObjectUtil { private static final String FORMAT_DATE_ISO = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; private static final DateFormat dateFormat = new SimpleDateFormat(FORMAT_DATE_ISO); + private static final String escapable = "[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]"; + private static final Pattern escapablePattern = Pattern.compile(escapable); + static { dateFormat.setTimeZone(TimeZone.getDefault()); } @@ -96,7 +100,12 @@ public static String serializeJSON(Object obj) { return serializeString(obj.toString()); } if (obj instanceof Number) { - return obj.toString(); + if (((Number)obj).intValue() == ((Number)obj).doubleValue()) { + return String.valueOf(new Integer(((Number)obj).intValue())); + } + else { + return obj.toString(); + } } if (obj instanceof XMLObject) { return serializeString(serializeXML((ScriptableObject) obj)); @@ -271,10 +280,46 @@ private static String serializeNativeError(Scriptable object) { return serializeJSON(o); } + private static String quote(String in) { + StringBuilder out = new StringBuilder(); + out.append("\""); + int len = in.length(); + for (int i = 0; i < len; i++) { + char c = in.charAt(i); + if (c == '\"') { + out.append("\\\""); + } + else if (c == '\\') { + out.append("\\\\"); + } + else if (c == '\b') { + out.append("\\b"); + } + else if (c == '\f') { + out.append("\\f"); + } + else if (c == '\n') { + out.append("\\n"); + } + else if (c == '\r') { + out.append("\\r"); + } + else if (c == '\t') { + out.append("\\t"); + } + else if (escapablePattern.matcher(String.valueOf(c)).matches()) { + out.append("\\u").append(String.format("%04X", (int) c)); + } + else { + out.append(c); + } + } + out.append("\""); + return out.toString(); + } + private static String serializeString(String obj) { - return "\"" + obj.replace("\\", "\\\\").replace("\"", "\\\"").replace("\r", "\\r").replace("\n", "\\n") - .replace("\t", "\\t").replace("\f", "\\f").replace("\b", "\\b").replace("\u2028", "\\u2028") - .replace("\u2029", "\\u2029") + "\""; + return quote(obj); } private static String serializeXML(ScriptableObject obj) { @@ -320,4 +365,4 @@ private static String serializeNativeObject(NativeObject obj) { json.append("}"); return json.toString(); } -} \ No newline at end of file +}