diff --git a/src/main/java/org/json/JSONObject.java b/src/main/java/org/json/JSONObject.java index 97a6df8d2..73d499a42 100644 --- a/src/main/java/org/json/JSONObject.java +++ b/src/main/java/org/json/JSONObject.java @@ -1159,6 +1159,18 @@ public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) { * to convert. */ static BigDecimal objectToBigDecimal(Object val, BigDecimal defaultValue) { + return objectToBigDecimal(val, defaultValue, true); + } + + /** + * @param val value to convert + * @param defaultValue default value to return is the conversion doesn't work or is null. + * @param exact When true, then {@link Double} and {@link Float} values will be converted exactly. + * When false, they will be converted to {@link String} values before converting to {@link BigDecimal}. + * @return BigDecimal conversion of the original value, or the defaultValue if unable + * to convert. + */ + static BigDecimal objectToBigDecimal(Object val, BigDecimal defaultValue, boolean exact) { if (NULL.equals(val)) { return defaultValue; } @@ -1172,7 +1184,14 @@ static BigDecimal objectToBigDecimal(Object val, BigDecimal defaultValue) { if (!numberIsFinite((Number)val)) { return defaultValue; } - return new BigDecimal(((Number) val).doubleValue()); + if (exact) { + return new BigDecimal(((Number)val).doubleValue()); + }else { + // use the string constructor so that we maintain "nice" values for doubles and floats + // the double constructor will translate doubles to "exact" values instead of the likely + // intended representation + return new BigDecimal(val.toString()); + } } if (val instanceof Long || val instanceof Integer || val instanceof Short || val instanceof Byte){ @@ -1639,9 +1658,6 @@ private static A getAnnotation(final Method m, final Clas * implementations and interfaces has the annotation. Returns the depth of the * annotation in the hierarchy. * - * @param - * type of the annotation - * * @param m * method to check * @param annotationClass @@ -2135,8 +2151,8 @@ static boolean isNumberSimilar(Number l, Number r) { // BigDecimal should be able to handle all of our number types that we support through // documentation. Convert to BigDecimal first, then use the Compare method to // decide equality. - final BigDecimal lBigDecimal = objectToBigDecimal(l, null); - final BigDecimal rBigDecimal = objectToBigDecimal(r, null); + final BigDecimal lBigDecimal = objectToBigDecimal(l, null, false); + final BigDecimal rBigDecimal = objectToBigDecimal(r, null, false); if (lBigDecimal == null || rBigDecimal == null) { return false; } diff --git a/src/main/java/org/json/JSONPointer.java b/src/main/java/org/json/JSONPointer.java index a3d1c1a2a..f1f7f3314 100644 --- a/src/main/java/org/json/JSONPointer.java +++ b/src/main/java/org/json/JSONPointer.java @@ -188,7 +188,7 @@ public JSONPointer(List refTokens) { } /** - * @see https://tools.ietf.org/html/rfc6901#section-3 + * @see rfc6901 section 3 */ private static String unescape(String token) { return token.replace("~1", "/").replace("~0", "~"); @@ -268,7 +268,7 @@ public String toString() { * @param token the JSONPointer segment value to be escaped * @return the escaped value for the token * - * @see https://tools.ietf.org/html/rfc6901#section-3 + * @see rfc6901 section 3 */ private static String escape(String token) { return token.replace("~", "~0") diff --git a/src/main/java/org/json/XMLParserConfiguration.java b/src/main/java/org/json/XMLParserConfiguration.java index b9e752c28..af3093bde 100644 --- a/src/main/java/org/json/XMLParserConfiguration.java +++ b/src/main/java/org/json/XMLParserConfiguration.java @@ -94,7 +94,7 @@ public XMLParserConfiguration (final boolean keepStrings) { * Configure the parser string processing to try and convert XML values to JSON values and * use the passed CDATA Tag Name the processing value. Pass null to * disable CDATA processing - * @param cDataTagNamenull to disable CDATA processing. Any other value + * @param cDataTagName null to disable CDATA processing. Any other value * to use that value as the JSONObject key name to process as CDATA. * @deprecated This constructor has been deprecated in favor of using the new builder * pattern for the configuration. @@ -109,7 +109,7 @@ public XMLParserConfiguration (final String cDataTagName) { * Configure the parser to use custom settings. * @param keepStrings true to parse all values as string. * false to try and convert XML string values into a JSON value. - * @param cDataTagNamenull to disable CDATA processing. Any other value + * @param cDataTagName null to disable CDATA processing. Any other value * to use that value as the JSONObject key name to process as CDATA. * @deprecated This constructor has been deprecated in favor of using the new builder * pattern for the configuration. @@ -182,7 +182,7 @@ protected XMLParserConfiguration clone() { * When parsing the XML into JSON, specifies if values should be kept as strings (true), or if * they should try to be guessed into JSON values (numeric, boolean, string) * - * @return The {@link #keepStrings} configuration value. + * @return The keepStrings configuration value. */ public boolean isKeepStrings() { return this.keepStrings; @@ -193,7 +193,7 @@ public boolean isKeepStrings() { * they should try to be guessed into JSON values (numeric, boolean, string) * * @param newVal - * new value to use for the {@link #keepStrings} configuration option. + * new value to use for the keepStrings configuration option. * * @return The existing configuration will not be modified. A new configuration is returned. */ @@ -208,7 +208,7 @@ public XMLParserConfiguration withKeepStrings(final boolean newVal) { * been the value "content" but can be changed. Use null to indicate no CDATA * processing. * - * @return The {@link #cDataTagName} configuration value. + * @return The cDataTagName configuration value. */ public String getcDataTagName() { return this.cDataTagName; @@ -220,7 +220,7 @@ public String getcDataTagName() { * processing. * * @param newVal - * new value to use for the {@link #cDataTagName} configuration option. + * new value to use for the cDataTagName configuration option. * * @return The existing configuration will not be modified. A new configuration is returned. */ @@ -235,7 +235,7 @@ public XMLParserConfiguration withcDataTagName(final String newVal) { * should be kept as attribute(false), or they should be converted to * null(true) * - * @return The {@link #convertNilAttributeToNull} configuration value. + * @return The convertNilAttributeToNull configuration value. */ public boolean isConvertNilAttributeToNull() { return this.convertNilAttributeToNull; @@ -247,7 +247,7 @@ public boolean isConvertNilAttributeToNull() { * null(true) * * @param newVal - * new value to use for the {@link #convertNilAttributeToNull} configuration option. + * new value to use for the convertNilAttributeToNull configuration option. * * @return The existing configuration will not be modified. A new configuration is returned. */ @@ -262,7 +262,7 @@ public XMLParserConfiguration withConvertNilAttributeToNull(final boolean newVal * will be converted to target type defined to client in this configuration * {@code Map>} to parse values with attribute * xsi:type="integer" as integer, xsi:type="string" as string - * @return {@link #xsiTypeMap} unmodifiable configuration map. + * @return xsiTypeMap unmodifiable configuration map. */ public Map> getXsiTypeMap() { return this.xsiTypeMap; diff --git a/src/test/java/org/json/junit/JSONObjectTest.java b/src/test/java/org/json/junit/JSONObjectTest.java index 0d5acdd2e..55290327e 100644 --- a/src/test/java/org/json/junit/JSONObjectTest.java +++ b/src/test/java/org/json/junit/JSONObjectTest.java @@ -126,6 +126,9 @@ public void verifySimilar() { assertTrue("Should eval to true", obj1.similar(obj4)); + // verify that a double and big decimal are "similar" + assertTrue("should eval to true",new JSONObject().put("a",1.1d).similar(new JSONObject("{\"a\":1.1}"))); + } @Test @@ -940,7 +943,7 @@ public void stringToValueNumbersTest() { assertTrue("-0 Should be a Double!",JSONObject.stringToValue("-0") instanceof Double); assertTrue("-0.0 Should be a Double!",JSONObject.stringToValue("-0.0") instanceof Double); assertTrue("'-' Should be a String!",JSONObject.stringToValue("-") instanceof String); - assertTrue( "0.2 should be a Double!", + assertTrue( "0.2 should be a BigDecimal!", JSONObject.stringToValue( "0.2" ) instanceof BigDecimal ); assertTrue( "Doubles should be BigDecimal, even when incorrectly converting floats!", JSONObject.stringToValue( new Double( "0.2f" ).toString() ) instanceof BigDecimal ); diff --git a/src/test/java/org/json/junit/JSONPointerTest.java b/src/test/java/org/json/junit/JSONPointerTest.java index f1b96849c..a72af3d0d 100644 --- a/src/test/java/org/json/junit/JSONPointerTest.java +++ b/src/test/java/org/json/junit/JSONPointerTest.java @@ -120,7 +120,7 @@ public void tildeEscaping() { /** * We pass backslashes as-is * - * @see https://tools.ietf.org/html/rfc6901#section-3 + * @see rfc6901 section 3 */ @Test public void backslashHandling() { @@ -130,7 +130,7 @@ public void backslashHandling() { /** * We pass quotations as-is * - * @see https://tools.ietf.org/html/rfc6901#section-3 + * @see rfc6901 section 3 */ @Test public void quotationHandling() { diff --git a/src/test/java/org/json/junit/data/ExceptionalBean.java b/src/test/java/org/json/junit/data/ExceptionalBean.java index 72d6c0cdb..91067b86b 100644 --- a/src/test/java/org/json/junit/data/ExceptionalBean.java +++ b/src/test/java/org/json/junit/data/ExceptionalBean.java @@ -8,7 +8,7 @@ import java.lang.reflect.InvocationTargetException; /** - * Object for testing the exception handling in {@link JSONObject#populateMap}. + * Object for testing the exception handling in {@link org.json.JSONObject#populateMap}. * * @author John Aylward */