You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@olingo.apache.org by Helmut Zimmer <he...@gmail.com> on 2017/07/07 13:04:35 UTC

Re: Jackson deserializes decimals incorrectly

Hi all,

I did some debugging and the problem is that Jackson (correctly)
creates a DoubleNode to represent the JSON node which is later
converted to string by Olingo (by calling JsonNode.asText()).
DoubleNode stores the internal value as double, and asText()
eventually calls Double.toString() which formats the double using
exponential notation.

So, Olingo should probably not rely on asText(), since the returned
String might not be the same as the input String (in the original
JSON). I guess the issue here is that the sole purpose of Jackson
ObjectMapper is to map JSON string values to Java data types, and that
is something that should not be done in the case of Olingo (since
Olingo should be the one doing the parsing/mapping). Naturally, this
probably could be solved also by having more relaxed type handling in
Olingo.

I resolved this issue by compiling my own version of Olingo
odata-client-core, where I made the following (really quick and dirty)
fix. This definitely is not the correct way to fix this issue and will
probably not work in every case, but for me it did the job:

@@ -284,13 +282,22 @@ public class JsonDeserializer implements
ODataDeserializer {
     }
   }

+  private static final DecimalFormat df;
+  static  {
+    //Set locale to English, so the decimal mark will be correctly formatted
+    df = new DecimalFormat("0",
DecimalFormatSymbols.getInstance(Locale.ENGLISH));
+    //Set the fraction digits to maximum allowed value
+    df.setMaximumFractionDigits(340);
+  }
   private Object fromPrimitive(final JsonNode node, final EdmTypeInfo
typeInfo) throws EdmPrimitiveTypeException {
     return node.isNull() ? null
         : typeInfo == null ? node.asText()
             : typeInfo.getPrimitiveTypeKind().isGeospatial()
             ? getGeoDeserializer().deserialize(node, typeInfo)
                 : ((EdmPrimitiveType) typeInfo.getType())
-                .valueOfString(node.asText(), true, null,
+                .valueOfString(node.isDouble() ?
+                                df.format(node.asDouble()) :
+                                node.asText(), true, null,
                     Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, true,
                     ((EdmPrimitiveType) typeInfo.getType()).getDefaultType());
   }



This was done on Olingo ver. 4.3.0


On Wed, Jun 28, 2017 at 1:38 PM, Helmut Zimmer <he...@gmail.com> wrote:
> Hi all,
>
> I have a problem with consuming  OData API provided Edm.Decimals using
> Olingo client. Whenever there is a long enough mantissa (e.g. 0.0004)
> Jackson deserializes the value to exponential notation (i.e. 4.0E-4)
> which then in turn fails validation in Olingo's EdmDecimal class
> (since exponential notation is not allowed on Edm.Decimal).
>
> The failed validation results in a thrown exception:
> Caused by: org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException:
> The literal '4.0E-4' has illegal content.
>         at org.apache.olingo.commons.core.edm.primitivetype.EdmDecimal.internalValueOfString(EdmDecimal.java:90)
>
>
> I see that this exact same problem has been discussed on this mailing
> list  a year ago ("Deserializing a decimal in scientific notation"),
> but back then there was no solution found. I also did not find any
> corresponding entry in the issue tracker for this.
>
> So, is there anything I can do? I can not change the API itself (i.e.
> change the type to e.g. double).
>
> Best Regards,
> Helmut