Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 2f2cd4d

Browse filesBrowse files
author
John J. Aylward
committed
Fix for number output bug.
java.lang.Number is currently output without any validation. For all java.* Numbers, this is fine, but for custom Number implementations like Complex or Fraction, the resulting JSON output may be invalid. For example: If a Fraction implementation defines its' toString method as `return numerator + "/" + denominator`, then the resulting JSON output would be something like this: ```json { "fraction" : 1/2 } ``` This is not valid JSON. This commit verifies that the string representation of the number is close to a JSON formatted number by use of the BigDecimal constructor. If the constructor throws a NumberFormatException, then the string value is instead quoted as a string. The example above would instead output like the following: ```json { "fraction" : "1/2" } ```
1 parent 7232a95 commit 2f2cd4d
Copy full SHA for 2f2cd4d

File tree

Expand file treeCollapse file tree

1 file changed

+37
-14
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

1 file changed

+37
-14
lines changed
Open diff view settings
Collapse file

‎JSONObject.java‎

Copy file name to clipboardExpand all lines: JSONObject.java
+37-14Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@ public static String numberToString(Number number) throws JSONException {
838838
}
839839
testValidity(number);
840840

841-
// Shave off trailing zeros and decimal point, if possible.
841+
// Shave off trailing zeros and decimal point, if possible.
842842

843843
String string = number.toString();
844844
if (string.indexOf('.') > 0 && string.indexOf('e') < 0
@@ -1693,7 +1693,18 @@ public static String valueToString(Object value) throws JSONException {
16931693
throw new JSONException("Bad value from toJSONString: " + object);
16941694
}
16951695
if (value instanceof Number) {
1696-
return numberToString((Number) value);
1696+
// not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
1697+
final String numberAsString = numberToString((Number) value);
1698+
try {
1699+
// Use the BigDecimal constructor for it's parser to validate the format.
1700+
new BigDecimal(numberAsString);
1701+
// Close enough to a JSON number that we will return it unquoted
1702+
return numberAsString;
1703+
} catch (NumberFormatException ex){
1704+
// The Number value is not a valid JSON number.
1705+
// Instead we will quote it as a string
1706+
return quote(numberAsString);
1707+
}
16971708
}
16981709
if (value instanceof Boolean || value instanceof JSONObject
16991710
|| value instanceof JSONArray) {
@@ -1783,6 +1794,30 @@ static final Writer writeValue(Writer writer, Object value,
17831794
int indentFactor, int indent) throws JSONException, IOException {
17841795
if (value == null || value.equals(null)) {
17851796
writer.write("null");
1797+
} else if (value instanceof JSONString) {
1798+
Object o;
1799+
try {
1800+
o = ((JSONString) value).toJSONString();
1801+
} catch (Exception e) {
1802+
throw new JSONException(e);
1803+
}
1804+
writer.write(o != null ? o.toString() : quote(value.toString()));
1805+
} else if (value instanceof Number) {
1806+
// not all Numbers may match actual JSON Numbers. i.e. fractions or Imaginary
1807+
final String numberAsString = numberToString((Number) value);
1808+
try {
1809+
// Use the BigDecimal constructor for it's parser to validate the format.
1810+
@SuppressWarnings("unused")
1811+
BigDecimal testNum = new BigDecimal(numberAsString);
1812+
// Close enough to a JSON number that we will use it unquoted
1813+
writer.write(numberAsString);
1814+
} catch (NumberFormatException ex){
1815+
// The Number value is not a valid JSON number.
1816+
// Instead we will quote it as a string
1817+
quote(numberAsString, writer);
1818+
}
1819+
} else if (value instanceof Boolean) {
1820+
writer.write(value.toString());
17861821
} else if (value instanceof JSONObject) {
17871822
((JSONObject) value).write(writer, indentFactor, indent);
17881823
} else if (value instanceof JSONArray) {
@@ -1795,18 +1830,6 @@ static final Writer writeValue(Writer writer, Object value,
17951830
new JSONArray(coll).write(writer, indentFactor, indent);
17961831
} else if (value.getClass().isArray()) {
17971832
new JSONArray(value).write(writer, indentFactor, indent);
1798-
} else if (value instanceof Number) {
1799-
writer.write(numberToString((Number) value));
1800-
} else if (value instanceof Boolean) {
1801-
writer.write(value.toString());
1802-
} else if (value instanceof JSONString) {
1803-
Object o;
1804-
try {
1805-
o = ((JSONString) value).toJSONString();
1806-
} catch (Exception e) {
1807-
throw new JSONException(e);
1808-
}
1809-
writer.write(o != null ? o.toString() : quote(value.toString()));
18101833
} else {
18111834
quote(value.toString(), writer);
18121835
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.