Skip to content

Commit

Permalink
Support non-strict compliance to JSON spec, re #12
Browse files Browse the repository at this point in the history
  • Loading branch information
safris committed May 26, 2023
1 parent 10d721c commit 2d08b82
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 11 deletions.
76 changes: 69 additions & 7 deletions src/main/java/org/openjax/json/JsonReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,33 +87,57 @@ public static JsonReader of(final Reader reader) {
private int nextStart = 0;

private final boolean ignoreWhitespace;
private final boolean strict;

/**
* Construct a new {@link JsonReader} for JSON content to be read from the specified {@link Reader}, <b>that ignores inter-token
* whitespace</b>. This constructor is equivalent to calling {@code new JsonReader(reader, true)}.
* Construct a new {@link JsonReader} for JSON content to be read from the specified {@link Reader}, that <b>ignores inter-token
* whitespace</b>, and <b>enforces strict compliance to the <a href="https://www.ietf.org/rfc/rfc4627.txt">JSON
* Specification</a></b>.
* <p>
* This constructor is equivalent to calling {@code new JsonReader(reader, true, true)}.
*
* @param reader The {@link Reader} from which JSON is to be read.
* @throws NullPointerException If {@code reader} is null.
*/
public JsonReader(final Reader reader) {
this(reader, true);
this(reader, true, true);
}

/**
* Construct a new {@link JsonReader} for JSON content to be read from the specified {@link Reader}.
* Construct a new {@link JsonReader} for JSON content to be read from the specified {@link Reader}, that <b>enforces strict
* compliance to the <a href="https://www.ietf.org/rfc/rfc4627.txt">JSON Specification</a></b>.
* <p>
* This constructor is equivalent to calling {@code new JsonReader(reader, ignoreWhitespace, true)}.
*
* @param reader The {@link Reader} from which JSON is to be read.
* @param ignoreWhitespace If {@code ignoreWhitespace == false}, inter-token whitespace will <b>not</b> be skipped.
* @throws NullPointerException If {@code reader} is null.
*/
public JsonReader(final Reader reader, final boolean ignoreWhitespace) {
this(reader, ignoreWhitespace, true);
}

/**
* Construct a new {@link JsonReader} for JSON content to be read from the specified {@link Reader}.
*
* @param reader The {@link Reader} from which JSON is to be read.
* @param ignoreWhitespace If {@code ignoreWhitespace == false}, inter-token whitespace will <b>not</b> be skipped.
* @param strict Whether to enforce strict compliance to the <a href="https://www.ietf.org/rfc/rfc4627.txt">JSON Specification</a>
* while parsing the JSON document.
* @throws NullPointerException If {@code reader} is null.
*/
public JsonReader(final Reader reader, final boolean ignoreWhitespace, final boolean strict) {
super(reader, DEFAULT_BUFFER_SIZE);
this.ignoreWhitespace = ignoreWhitespace;
this.strict = strict;
}

/**
* Construct a new {@link JsonReader} for JSON content to be read from the specified string, <b>that ignores inter-token
* whitespace</b>. This constructor is equivalent to calling {@code new JsonReader(str, true)}.
* whitespace</b>, and <b>enforces strict compliance to the <a href="https://www.ietf.org/rfc/rfc4627.txt">JSON
* Specification</a></b>.
* <p>
* This constructor is equivalent to calling {@code new JsonReader(str, true, true)}.
*
* @param str The string with the JSON document to be read.
* @throws NullPointerException If {@code str} is null.
Expand All @@ -123,15 +147,52 @@ public JsonReader(final String str) {
}

/**
* Construct a new {@link JsonReader} for JSON content to be read from the specified string.
* Construct a new {@link JsonReader} for JSON content to be read from the specified string, that <b>enforces strict compliance to
* the <a href="https://www.ietf.org/rfc/rfc4627.txt">JSON Specification</a></b>.
* <p>
* This constructor is equivalent to calling {@code new JsonReader(str, ignoreWhitespace, true)}.
*
* @param str The string with the JSON document to be read.
* @param ignoreWhitespace If {@code ignoreWhitespace == false}, inter-token whitespace will <b>not</b> be skipped.
* @throws NullPointerException If {@code str} is null.
*/
public JsonReader(final String str, final boolean ignoreWhitespace) {
this(str, ignoreWhitespace, true);
}

/**
* Construct a new {@link JsonReader} for JSON content to be read from the specified string.
*
* @param str The string with the JSON document to be read.
* @param strict Whether to enforce strict compliance to the <a href="https://www.ietf.org/rfc/rfc4627.txt">JSON Specification</a>
* while parsing the JSON document.
* @param ignoreWhitespace If {@code ignoreWhitespace == false}, inter-token whitespace will <b>not</b> be skipped.
* @throws NullPointerException If {@code str} is null.
*/
public JsonReader(final String str, final boolean ignoreWhitespace, final boolean strict) {
super(new UnsynchronizedStringReader(str), DEFAULT_BUFFER_SIZE);
this.ignoreWhitespace = ignoreWhitespace;
this.strict = strict;
}

/**
* Returns whether this {@link JsonReader} skips inter-token whitespace.
*
* @return Whether this {@link JsonReader} skips inter-token whitespace.
*/
public boolean isIgnoreWhitespace() {
return ignoreWhitespace;
}

/**
* Returns whether this {@link JsonReader} enforces strict compliance to the <a href="https://www.ietf.org/rfc/rfc4627.txt">JSON
* Specification</a>.
*
* @return Whether this {@link JsonReader} enforces strict compliance to the <a href="https://www.ietf.org/rfc/rfc4627.txt">JSON
* Specification</a>.
*/
public boolean isStrict() {
return strict;
}

/**
Expand Down Expand Up @@ -826,7 +887,8 @@ else if (ch < '0' || '9' < ch) {
break;
}
else if (prev == '0' && i == (first == '~' ? 2 : 1)) {
throw new JsonParseException("Leading zeros are not allowed", getPosition() - 2);
if (strict)
throw new JsonParseException("Leading zeros are not allowed", getPosition() - 2);
}
}

Expand Down
7 changes: 5 additions & 2 deletions src/main/java/org/openjax/json/JsonUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,16 @@ public static boolean isWhitespace(final int ch) {
* @param <T> The type parameter for the return instance.
* @param type The class of the return instance.
* @param str The {@link CharSequence} to parse.
* @param strict Whether to enforce strict compliance to the <a href="https://www.ietf.org/rfc/rfc4627.txt">JSON Specification</a>
* while parsing the JSON document.
* @return An instance of class {@code type} representing the parsed string.
* @throws JsonParseException If a parsing error has occurred.
* @throws IllegalArgumentException If the specified string is empty, or if an instance of the specific class type does not define
* {@code <init>(String)}, {@code valueOf(String)}, or {@code fromString(String)}.
* @throws NullPointerException If {@code str} is null.
*/
@SuppressWarnings("unchecked")
public static <T extends Number>T parseNumber(final Class<T> type, CharSequence str) throws JsonParseException {
public static <T extends Number>T parseNumber(final Class<T> type, CharSequence str, final boolean strict) throws JsonParseException {
if (str.length() == 0)
throw new IllegalArgumentException("Empty string");

Expand Down Expand Up @@ -122,7 +124,8 @@ else if (ch < '0' || '9' < ch) {
break;
}
else if (last == '0' && i == expStart + (first == '~' ? 2 : 1)) {
throw new JsonParseException("Leading zeros are not allowed", i - 1);
if (strict)
throw new JsonParseException("Leading zeros are not allowed", i - 1);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/test/java/org/openjax/json/JsonTypesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ public void testIsWhitespace() {
}

private static void testPass(final String number, final Class<? extends Number> type) {
JsonUtil.parseNumber(type, number);
JsonUtil.parseNumber(type, number, true);
}

private static void testFail(final Class<? extends Exception> cls, final String number) {
try {
JsonUtil.parseNumber(BigDecimal.class, number);
JsonUtil.parseNumber(BigDecimal.class, number, true);
fail("Expected " + cls.getSimpleName());
}
catch (final Exception e) {
Expand Down

0 comments on commit 2d08b82

Please sign in to comment.