This is an automated email from the ASF dual-hosted git repository.

benweidig pushed a commit to branch TAP5-2837
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git

commit b9a233cc52626b4855c923ca0061835130f25c13
Author: Ben Weidig <[email protected]>
AuthorDate: Sun Jul 26 14:50:08 2026 +0200

    TAP5-2837: Improve JSON serialization performance
---
 .../org/apache/tapestry5/json/CompactSession.java  |  23 ++-
 .../org/apache/tapestry5/json/JSONCollection.java  |  36 ++--
 .../java/org/apache/tapestry5/json/JSONObject.java | 200 ++++++++++++++++++---
 .../org/apache/tapestry5/json/JSONPrintSink.java   |  92 ++++++++++
 .../org/apache/tapestry5/json/JSONStringer.java    |   3 +
 .../org/apache/tapestry5/json/JSONTokener.java     |   4 +-
 .../apache/tapestry5/json/PrettyPrintSession.java  |  41 +++--
 .../org/apache/tapestry5/json/package-info.java    |   4 +-
 .../org/apache/tapestry5/json/JSONObjectTest.java  |  15 +-
 9 files changed, 355 insertions(+), 63 deletions(-)

diff --git 
a/tapestry-json/src/main/java/org/apache/tapestry5/json/CompactSession.java 
b/tapestry-json/src/main/java/org/apache/tapestry5/json/CompactSession.java
index 8eced6925..55127a23a 100644
--- a/tapestry-json/src/main/java/org/apache/tapestry5/json/CompactSession.java
+++ b/tapestry-json/src/main/java/org/apache/tapestry5/json/CompactSession.java
@@ -1,4 +1,4 @@
-// Copyright 2010 The Apache Software Foundation
+// Copyright 2010, 2026 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -18,16 +18,21 @@ import java.io.PrintWriter;
 
 /**
  * Prints the JSON content compactly, with no indentation or extra whitespace.
- * 
+ *
  * @since 5.2.0
  */
 class CompactSession implements JSONPrintSession
 {
-    private final PrintWriter writer;
+    private final JSONPrintSink out;
+
+    CompactSession(StringBuilder out)
+    {
+        this.out = new StringBuilderPrintSink(out);
+    }
 
     public CompactSession(PrintWriter writer)
     {
-        this.writer = writer;
+        this.out = new WriterPrintSink(writer);
     }
 
     @Override
@@ -51,7 +56,7 @@ class CompactSession implements JSONPrintSession
     @Override
     public JSONPrintSession print(String value)
     {
-        writer.print(value);
+        out.append(value);
 
         return this;
     }
@@ -59,13 +64,17 @@ class CompactSession implements JSONPrintSession
     @Override
     public JSONPrintSession printQuoted(String value)
     {
-        return print(JSONObject.quote(value));
+        out.append('"');
+        JSONObject.escapeInto(out, value);
+        out.append('"');
+
+        return this;
     }
 
     @Override
     public JSONPrintSession printSymbol(char symbol)
     {
-        writer.print(symbol);
+        out.append(symbol);
 
         return this;
     }
diff --git 
a/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONCollection.java 
b/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONCollection.java
index c5ee1082c..0615bc47a 100644
--- a/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONCollection.java
+++ b/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONCollection.java
@@ -12,7 +12,6 @@
 
 package org.apache.tapestry5.json;
 
-import java.io.CharArrayWriter;
 import java.io.PrintWriter;
 import java.io.Serializable;
 
@@ -38,16 +37,13 @@ public abstract class JSONCollection implements Serializable
     @Override
     public String toString()
     {
-        CharArrayWriter caw = new CharArrayWriter();
-        PrintWriter pw = new PrintWriter(caw);
+        StringBuilder out = new StringBuilder(estimateCapacity());
 
-        JSONPrintSession session = new PrettyPrintSession(pw);
+        JSONPrintSession session = new PrettyPrintSession(out);
 
         print(session);
 
-        pw.close();
-
-        return caw.toString();
+        return out.toString();
     }
 
     /**
@@ -68,16 +64,32 @@ public abstract class JSONCollection implements Serializable
      */
     public String toCompactString()
     {
-        CharArrayWriter caw = new CharArrayWriter();
-        PrintWriter pw = new PrintWriter(caw);
+        StringBuilder out = new StringBuilder(estimateCapacity());
 
-        print(pw);
+        JSONPrintSession session = new CompactSession(out);
 
-        pw.close();
+        print(session);
 
-        return caw.toString();
+        return out.toString();
+    }
+
+    /**
+     * A cheap starting capacity for the {@link StringBuilder} backing {@link 
#toString()} /
+     * {@link #toCompactString()}, to avoid repeated grow-and-copy cycles for 
non-trivial trees.
+     * Scales with the top-level collection's element count only; recursing 
into nested
+     * collections isn't worth the extra bookkeeping for a rough estimate.
+     */
+    private int estimateCapacity()
+    {
+        return Math.max(256, size() * 32);
     }
 
+    /**
+     * The number of top-level entries (name/value pairs for {@link 
JSONObject}, elements for
+     * {@link JSONArray}), used only to estimate a starting buffer capacity.
+     */
+    abstract int size();
+
     /**
      * Prints the JSONObject to the write (compactly or not).
      * 
diff --git 
a/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONObject.java 
b/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONObject.java
index 321085ed5..b7f034549 100644
--- a/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONObject.java
+++ b/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONObject.java
@@ -775,14 +775,154 @@ public final class JSONObject extends JSONCollection 
implements Map<String, Obje
         if (data == null) {
             return "\"\"";
         }
-        try {
-            JSONStringer stringer = new JSONStringer();
-            stringer.open(JSONStringer.Scope.NULL, "");
-            stringer.string(data);
-            stringer.close(JSONStringer.Scope.NULL, JSONStringer.Scope.NULL, 
"");
-            return stringer.toString();
-        } catch (RuntimeException e) {
-            throw new AssertionError();
+
+        StringBuilder out = new StringBuilder(data.length() + 8);
+        out.append('"');
+        escapeInto(out, data);
+        out.append('"');
+        return out.toString();
+    }
+
+    private static final char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
+
+    /**
+     * Appends the escaped (but not quoted) form of {@code value} to {@code 
out}: the same
+     * character escaping rules as {@link #quote(String)}, without allocating 
an intermediate
+     * String or wrapping quotes.
+     * 
+     * <p>This is the direct-to-{@link StringBuilder} fast path used by {@code 
quote()} itself,
+     * which always targets a StringBuilder and is called often enough (once 
per printed string/key)
+     * that the {@link JSONPrintSink} indirection used by {@link 
#escapeInto(JSONPrintSink, String)}
+     * measurably costs more than it's worth here. See {@link 
#escapeInto(JSONPrintSink, String)}
+     * for the print-session variant.
+     */
+    static void escapeInto(StringBuilder out, String value) {
+        char currentChar = 0;
+
+        for (int i = 0, length = value.length(); i < length; i++) {
+            char previousChar = currentChar;
+            currentChar = value.charAt(i);
+
+            /*
+             * From RFC 4627, "All Unicode characters may be placed within the
+             * quotation marks except for the characters that must be escaped:
+             * quotation mark, reverse solidus, and the control characters
+             * (U+0000 through U+001F)."
+             */
+            switch (currentChar) {
+                case '"':
+                case '\\':
+                    out.append('\\').append(currentChar);
+                    break;
+
+                case '/':
+                    // it makes life easier for HTML embedding of javascript 
if we escape </ sequences
+                    if (previousChar == '<') {
+                        out.append('\\');
+                    }
+                    out.append(currentChar);
+                    break;
+
+                case '\t':
+                    out.append("\\t");
+                    break;
+
+                case '\b':
+                    out.append("\\b");
+                    break;
+
+                case '\n':
+                    out.append("\\n");
+                    break;
+
+                case '\r':
+                    out.append("\\r");
+                    break;
+
+                case '\f':
+                    out.append("\\f");
+                    break;
+
+                default:
+                    if (currentChar <= 0x1F || (currentChar >= 0x0080 && 
currentChar < 0x00a0) || (currentChar >= 0x2000 && currentChar < 0x2100)) {
+                        out.append('\\').append('u')
+                           .append(HEX_DIGITS[(currentChar >> 12) & 0xF])
+                           .append(HEX_DIGITS[(currentChar >> 8) & 0xF])
+                           .append(HEX_DIGITS[(currentChar >> 4) & 0xF])
+                           .append(HEX_DIGITS[currentChar & 0xF]);
+                    } else {
+                        out.append(currentChar);
+                    }
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Same escaping rules as {@link #escapeInto(StringBuilder, String)}, 
targeting a
+     * {@link JSONPrintSink} instead.
+     * 
+     * <p>Used by the print sessions, whose destination varies between an 
in-memory
+     * {@link StringBuilder} ({@code toString()}/{@code toCompactString()}) 
and a
+     * caller-supplied {@link java.io.PrintWriter} ({@code print(PrintWriter, 
boolean)}),
+     * so they can escape directly into whichever one they were constructed 
with.
+     * 
+     * <p>Note: Having dedicated methods for the types instead of a 
classifying mechanism
+     * keeps the call site monomorphic for the JVM, allowing for greater 
optimization
+     * potential.
+     */
+    static void escapeInto(JSONPrintSink out, String value) {
+        char currentChar = 0;
+
+        for (int i = 0, length = value.length(); i < length; i++) {
+            char previousChar = currentChar;
+            currentChar = value.charAt(i);
+
+            switch (currentChar) {
+                case '"':
+                case '\\':
+                    out.append('\\').append(currentChar);
+                    break;
+
+                case '/':
+                    if (previousChar == '<') {
+                        out.append('\\');
+                    }
+                    out.append(currentChar);
+                    break;
+
+                case '\t':
+                    out.append("\\t");
+                    break;
+
+                case '\b':
+                    out.append("\\b");
+                    break;
+
+                case '\n':
+                    out.append("\\n");
+                    break;
+
+                case '\r':
+                    out.append("\\r");
+                    break;
+
+                case '\f':
+                    out.append("\\f");
+                    break;
+
+                default:
+                    if (currentChar <= 0x1F || (currentChar >= 0x0080 && 
currentChar < 0x00a0) || (currentChar >= 0x2000 && currentChar < 0x2100)) {
+                        out.append('\\').append('u')
+                           .append(HEX_DIGITS[(currentChar >> 12) & 0xF])
+                           .append(HEX_DIGITS[(currentChar >> 8) & 0xF])
+                           .append(HEX_DIGITS[(currentChar >> 4) & 0xF])
+                           .append(HEX_DIGITS[currentChar & 0xF]);
+                    } else {
+                        out.append(currentChar);
+                    }
+                    break;
+            }
         }
     }
 
@@ -826,7 +966,6 @@ public final class JSONObject extends JSONCollection 
implements Map<String, Obje
         session.printSymbol('}');
     }
 
-
     /**
      * Prints a value (a JSONArray or JSONObject, or a value stored in an 
array or object) using
      * the session.
@@ -835,48 +974,61 @@ public final class JSONObject extends JSONCollection 
implements Map<String, Obje
      */
     static void printValue(JSONPrintSession session, Object value)
     {
+        // Orderd by (assumed) most common frequency in JSON
 
+        // Null Check: Must be first.
         if (value == null || value == NULL)
         {
             session.print("null");
             return;
         }
-        if (value instanceof JSONObject)
-        {
-            ((JSONObject) value).print(session);
-            return;
-        }
 
-        if (value instanceof JSONArray)
+        // String: Explicitly checking here prevents the most common 
+        // JSON type from falling through all other checks.
+        if (value instanceof String)
         {
-            ((JSONArray) value).print(session);
+            session.printQuoted((String) value);
             return;
         }
 
-        if (value instanceof JSONString)
+        // Number: Highly common in JSON payloads.
+        if (value instanceof Number)
         {
-            String printValue = ((JSONString) value).toJSONString();
-
+            String printValue = numberToString((Number) value);
             session.print(printValue);
-
             return;
         }
 
-        if (value instanceof Number)
+        // JSONObject: The primary structural container.
+        if (value instanceof JSONObject)
         {
-            String printValue = numberToString((Number) value);
-            session.print(printValue);
+            ((JSONObject) value).print(session);
             return;
         }
 
+        // Boolean: Common, but usually fewer instances per payload than 
numbers.
         if (value instanceof Boolean)
         {
             session.print(value.toString());
+            return;
+        }
 
+        // JSONArray: Generally fewer arrays than objects in nested structures.
+        if (value instanceof JSONArray)
+        {
+            ((JSONArray) value).print(session);
+            return;
+        }
+
+        // JSONString: Kept near the bottom assuming it is a custom wrapper.
+        if (value instanceof JSONString)
+        {
+            String printValue = ((JSONString) value).toJSONString();
+            session.print(printValue);
             return;
         }
 
-        // Otherwise it really should just be a string. Nothing else can go in.
+        // Fallback for any other unexpected objects
         session.printQuoted(value.toString());
     }
 
diff --git 
a/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONPrintSink.java 
b/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONPrintSink.java
new file mode 100644
index 000000000..ccd843af9
--- /dev/null
+++ b/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONPrintSink.java
@@ -0,0 +1,92 @@
+// Copyright 2026 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.json;
+
+import java.io.PrintWriter;
+
+/**
+ * The destination a {@link JSONPrintSession} (and {@link 
JSONObject#escapeInto}) writes
+ * characters to: either an in-memory buffer (for {@code toString()}/{@code 
toCompactString()})
+ * or a caller-supplied {@link PrintWriter} (for {@code print(PrintWriter, 
boolean)}).
+ *
+ * <p>Deliberately narrower than {@link Appendable}: neither implementation 
below can actually throw
+ * {@link java.io.IOException}, so this avoids forcing checked-exception 
handling onto every
+ * append call in the hot print path.
+ */
+interface JSONPrintSink
+{
+    JSONPrintSink append(String value);
+
+    JSONPrintSink append(char value);
+}
+
+/**
+ * Sink backed by an in-memory {@link StringBuilder}, used to build a {@code 
String} directly
+ * without an intermediate {@code CharArrayWriter}/{@code PrintWriter} pair.
+ */
+class StringBuilderPrintSink implements JSONPrintSink
+{
+    private final StringBuilder out;
+
+    StringBuilderPrintSink(StringBuilder out)
+    {
+        this.out = out;
+    }
+
+    @Override
+    public JSONPrintSink append(String value)
+    {
+        out.append(value);
+
+        return this;
+    }
+
+    @Override
+    public JSONPrintSink append(char value)
+    {
+        out.append(value);
+
+        return this;
+    }
+}
+
+/**
+ * Sink backed by a caller-supplied {@link PrintWriter}, used by {@code 
print(PrintWriter, boolean)}.
+ */
+class WriterPrintSink implements JSONPrintSink
+{
+    private final PrintWriter writer;
+
+    WriterPrintSink(PrintWriter writer)
+    {
+        this.writer = writer;
+    }
+
+    @Override
+    public JSONPrintSink append(String value)
+    {
+        writer.print(value);
+
+        return this;
+    }
+
+    @Override
+    public JSONPrintSink append(char value)
+    {
+        writer.write(value);
+
+        return this;
+    }
+}
diff --git 
a/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONStringer.java 
b/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONStringer.java
index 861263574..d49b6c3a1 100644
--- a/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONStringer.java
+++ b/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONStringer.java
@@ -57,7 +57,10 @@ import java.util.List;
  * self-use by overrideable methods is not specified. See <i>Effective Java</i>
  * Item 17, "Design and Document or inheritance or else prohibit it" for 
further
  * information.
+ * 
+ * @deprecated in 5.10.0 without a replacement.
  */
+@Deprecated
 class JSONStringer {
 
     /**
diff --git 
a/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONTokener.java 
b/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONTokener.java
index e0c4dac3c..225c8c26c 100644
--- a/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONTokener.java
+++ b/tapestry-json/src/main/java/org/apache/tapestry5/json/JSONTokener.java
@@ -476,14 +476,14 @@ class JSONTokener {
                 case ',':
                 case ';':
                     /* A separator without a value first means "null". */
-                    result.put(JSONObject.NULL);
+                    result.add(JSONObject.NULL);
                     hasTrailingSeparator = true;
                     continue;
                 default:
                     pos--;
             }
 
-            result.put(nextValue(null));
+            result.add(nextValue(null));
 
             switch (nextCleanInternal()) {
                 case ']':
diff --git 
a/tapestry-json/src/main/java/org/apache/tapestry5/json/PrettyPrintSession.java 
b/tapestry-json/src/main/java/org/apache/tapestry5/json/PrettyPrintSession.java
index 8f0c5f31b..729f0c39b 100644
--- 
a/tapestry-json/src/main/java/org/apache/tapestry5/json/PrettyPrintSession.java
+++ 
b/tapestry-json/src/main/java/org/apache/tapestry5/json/PrettyPrintSession.java
@@ -1,4 +1,4 @@
-// Copyright 2010 The Apache Software Foundation
+// Copyright 2010, 2026 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -18,12 +18,12 @@ import java.io.PrintWriter;
 
 /**
  * Used to pretty-print JSON content, with a customizable indentation.
- * 
+ *
  * @since 5.2.0
  */
 class PrettyPrintSession implements JSONPrintSession
 {
-    private final PrintWriter writer;
+    private final JSONPrintSink out;
 
     private final String indentString;
 
@@ -36,10 +36,16 @@ class PrettyPrintSession implements JSONPrintSession
 
     private Position position = Position.MARGIN;
 
+    /** Defaults the indentation to be two spaces per indentation level. */
+    PrettyPrintSession(StringBuilder out)
+    {
+        this(new StringBuilderPrintSink(out), "  ");
+    }
+
     /** Defaults the indentation to be two spaces per indentation level. */
     public PrettyPrintSession(PrintWriter writer)
     {
-        this(writer, "  ");
+        this(new WriterPrintSink(writer), "  ");
     }
 
     /**
@@ -50,7 +56,12 @@ class PrettyPrintSession implements JSONPrintSession
      */
     public PrettyPrintSession(PrintWriter writer, String indentString)
     {
-        this.writer = writer;
+        this(new WriterPrintSink(writer), indentString);
+    }
+
+    private PrettyPrintSession(JSONPrintSink out, String indentString)
+    {
+        this.out = out;
         this.indentString = indentString;
     }
 
@@ -67,7 +78,7 @@ class PrettyPrintSession implements JSONPrintSession
     {
         if (position != Position.MARGIN)
         {
-            writer.write('\n');
+            out.append('\n');
             position = Position.MARGIN;
         }
 
@@ -87,7 +98,7 @@ class PrettyPrintSession implements JSONPrintSession
         if (position == Position.MARGIN)
         {
             for (int i = 0; i < indentLevel; i++)
-                writer.print(indentString);
+                out.append(indentString);
 
             position = Position.INDENTED;
         }
@@ -97,7 +108,7 @@ class PrettyPrintSession implements JSONPrintSession
     {
         if (position == Position.CONTENT)
         {
-            writer.print(' ');
+            out.append(' ');
         }
     }
 
@@ -113,7 +124,7 @@ class PrettyPrintSession implements JSONPrintSession
     {
         prepareToPrint();
 
-        writer.print(value);
+        out.append(value);
 
         position = Position.CONTENT;
 
@@ -123,7 +134,15 @@ class PrettyPrintSession implements JSONPrintSession
     @Override
     public JSONPrintSession printQuoted(String value)
     {
-        return print(JSONObject.quote(value));
+        prepareToPrint();
+
+        out.append('"');
+        JSONObject.escapeInto(out, value);
+        out.append('"');
+
+        position = Position.CONTENT;
+
+        return this;
     }
 
     @Override
@@ -134,7 +153,7 @@ class PrettyPrintSession implements JSONPrintSession
         if (symbol != ',')
             addSep();
 
-        writer.print(symbol);
+        out.append(symbol);
 
         return this;
     }
diff --git 
a/tapestry-json/src/main/java/org/apache/tapestry5/json/package-info.java 
b/tapestry-json/src/main/java/org/apache/tapestry5/json/package-info.java
index 464082c05..2d5a6715a 100644
--- a/tapestry-json/src/main/java/org/apache/tapestry5/json/package-info.java
+++ b/tapestry-json/src/main/java/org/apache/tapestry5/json/package-info.java
@@ -13,7 +13,7 @@
 /**
  * Repackaged, improved (and tested) version of code originally 
https://github.com/tdunning/open-json
  *
- * Starting in release 5.4, {@link org.apache.tapestry5.json.JSONObject} and 
{@link org.apache.tapestry5.json.JSONArray}
+ * Starting in release 5.4, {@link 
org.apache.tapestry5.json.improved.JSONObject} and {@link 
org.apache.tapestry5.json.improved.JSONArray}
  * are serializable.
  */
-package org.apache.tapestry5.json;
+package org.apache.tapestry5.json.improved;
diff --git 
a/tapestry-json/src/test/java/org/apache/tapestry5/json/JSONObjectTest.java 
b/tapestry-json/src/test/java/org/apache/tapestry5/json/JSONObjectTest.java
index 0b4167a80..64689de9d 100644
--- a/tapestry-json/src/test/java/org/apache/tapestry5/json/JSONObjectTest.java
+++ b/tapestry-json/src/test/java/org/apache/tapestry5/json/JSONObjectTest.java
@@ -1,4 +1,4 @@
-// Copyright 2025 The Apache Software Foundation
+// Copyright 2025, 2026 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -320,8 +320,8 @@ public class JSONObjectTest {
 
         JSONObject object = new JSONObject("{fred: 'flintstone'}");
 
-        assertTrue(object.has("fred"));
-        assertFalse(object.has("barney"));
+        assertTrue(object.containsKey("fred"));
+        assertFalse(object.containsKey("barney"));
     }
 
     @Test
@@ -456,7 +456,12 @@ public class JSONObjectTest {
         return Stream.of(
             Arguments.of(null, "\"\"", "null is empty string"),
             Arguments.of("", "\"\"", "empty string is empty string"),
-            Arguments.of("\"/\b\t\n\f\r\u2001/a</", 
"\"\\\"/\\b\\t\\n\\f\\r\\u2001/a<\\/\"", "special characters")
+            Arguments.of("\"/\b\t\n\f\r\u2001/a</", 
"\"\\\"/\\b\\t\\n\\f\\r\\u2001/a<\\/\"", "special characters"),
+            Arguments.of(
+                " \u0080\u009f\u00a0\u1fff\u2000\u20ff\u2100",
+                "\"\\u001f \\u0080\\u009f\u00a0\u1fff\\u2000\\u20ff\u2100\"",
+                "escape range boundaries: 0x1F/0x20, 0x7F/0x80/0x9F/0xA0, 
0x1FFF/0x2000/0x20FF/0x2100"
+            )
         );
     }
 
@@ -888,4 +893,4 @@ public class JSONObjectTest {
 
         assertEquals(defaultValue, value);
     }
-}
\ No newline at end of file
+}

Reply via email to