mirror of
https://github.com/ethauvin/JSON-java.git
synced 2025-06-17 07:50:52 -07:00
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" } ```
This commit is contained in:
parent
7232a95c0b
commit
2f2cd4dfc5
1 changed files with 37 additions and 14 deletions
|
@ -838,7 +838,7 @@ public class JSONObject {
|
||||||
}
|
}
|
||||||
testValidity(number);
|
testValidity(number);
|
||||||
|
|
||||||
// Shave off trailing zeros and decimal point, if possible.
|
// Shave off trailing zeros and decimal point, if possible.
|
||||||
|
|
||||||
String string = number.toString();
|
String string = number.toString();
|
||||||
if (string.indexOf('.') > 0 && string.indexOf('e') < 0
|
if (string.indexOf('.') > 0 && string.indexOf('e') < 0
|
||||||
|
@ -1693,7 +1693,18 @@ public class JSONObject {
|
||||||
throw new JSONException("Bad value from toJSONString: " + object);
|
throw new JSONException("Bad value from toJSONString: " + object);
|
||||||
}
|
}
|
||||||
if (value instanceof Number) {
|
if (value instanceof Number) {
|
||||||
return numberToString((Number) value);
|
// not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
|
||||||
|
final String numberAsString = numberToString((Number) value);
|
||||||
|
try {
|
||||||
|
// Use the BigDecimal constructor for it's parser to validate the format.
|
||||||
|
new BigDecimal(numberAsString);
|
||||||
|
// Close enough to a JSON number that we will return it unquoted
|
||||||
|
return numberAsString;
|
||||||
|
} catch (NumberFormatException ex){
|
||||||
|
// The Number value is not a valid JSON number.
|
||||||
|
// Instead we will quote it as a string
|
||||||
|
return quote(numberAsString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (value instanceof Boolean || value instanceof JSONObject
|
if (value instanceof Boolean || value instanceof JSONObject
|
||||||
|| value instanceof JSONArray) {
|
|| value instanceof JSONArray) {
|
||||||
|
@ -1783,6 +1794,30 @@ public class JSONObject {
|
||||||
int indentFactor, int indent) throws JSONException, IOException {
|
int indentFactor, int indent) throws JSONException, IOException {
|
||||||
if (value == null || value.equals(null)) {
|
if (value == null || value.equals(null)) {
|
||||||
writer.write("null");
|
writer.write("null");
|
||||||
|
} else if (value instanceof JSONString) {
|
||||||
|
Object o;
|
||||||
|
try {
|
||||||
|
o = ((JSONString) value).toJSONString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new JSONException(e);
|
||||||
|
}
|
||||||
|
writer.write(o != null ? o.toString() : quote(value.toString()));
|
||||||
|
} else if (value instanceof Number) {
|
||||||
|
// not all Numbers may match actual JSON Numbers. i.e. fractions or Imaginary
|
||||||
|
final String numberAsString = numberToString((Number) value);
|
||||||
|
try {
|
||||||
|
// Use the BigDecimal constructor for it's parser to validate the format.
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
BigDecimal testNum = new BigDecimal(numberAsString);
|
||||||
|
// Close enough to a JSON number that we will use it unquoted
|
||||||
|
writer.write(numberAsString);
|
||||||
|
} catch (NumberFormatException ex){
|
||||||
|
// The Number value is not a valid JSON number.
|
||||||
|
// Instead we will quote it as a string
|
||||||
|
quote(numberAsString, writer);
|
||||||
|
}
|
||||||
|
} else if (value instanceof Boolean) {
|
||||||
|
writer.write(value.toString());
|
||||||
} else if (value instanceof JSONObject) {
|
} else if (value instanceof JSONObject) {
|
||||||
((JSONObject) value).write(writer, indentFactor, indent);
|
((JSONObject) value).write(writer, indentFactor, indent);
|
||||||
} else if (value instanceof JSONArray) {
|
} else if (value instanceof JSONArray) {
|
||||||
|
@ -1795,18 +1830,6 @@ public class JSONObject {
|
||||||
new JSONArray(coll).write(writer, indentFactor, indent);
|
new JSONArray(coll).write(writer, indentFactor, indent);
|
||||||
} else if (value.getClass().isArray()) {
|
} else if (value.getClass().isArray()) {
|
||||||
new JSONArray(value).write(writer, indentFactor, indent);
|
new JSONArray(value).write(writer, indentFactor, indent);
|
||||||
} else if (value instanceof Number) {
|
|
||||||
writer.write(numberToString((Number) value));
|
|
||||||
} else if (value instanceof Boolean) {
|
|
||||||
writer.write(value.toString());
|
|
||||||
} else if (value instanceof JSONString) {
|
|
||||||
Object o;
|
|
||||||
try {
|
|
||||||
o = ((JSONString) value).toJSONString();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new JSONException(e);
|
|
||||||
}
|
|
||||||
writer.write(o != null ? o.toString() : quote(value.toString()));
|
|
||||||
} else {
|
} else {
|
||||||
quote(value.toString(), writer);
|
quote(value.toString(), writer);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue