Last Updated on 03/05/2021 by Patryk Bandurski
In the last article, I have described a nuisance with casting to an integer value. This time we will look at huge numbers and their formatting. In addition, I will mention scientific notation. All these topics are around the number format used by the DataWeave engine. So let’s see what the problem looks like.
Problem
This problem may not be obvious. What is more, it may not happen for a long, very long time. Would you consider in your XML/json document value 4.5E7 a correct number? Although in json schema, exponential (scientific) notation is considered a correct one, clients may not handle it if they are not aware of such possible notation. In XML decimal type marks this notation is an invalid one.
You may ask, so what is the problem here, mate. The answer is easy. DataWeave uses one internal data type to represent a number/integer. In some arithmetic operations like multiplication/division, the DataWeave engine will try to preserve precision loss. Instead of a typical decimal number, we will receive a number in exponential notation. Like in the example below:
%dw 2.0
output application/dw
---
{
total: (payload.price * payload.quantity) * (1-payload.discount/100)
}
If we try to transform following input value
{
"quantity": 50,
"price": 1000000,
"discount": 10
}
DataWeave will produce something like this:
{
total: 4.5E7
}
However, I do not like the returned value. I would like to have a standard notation as I, later on, transform this to XML, and this is not a correct value. The expected value is 45000000. This problem will not occur if the number will be less than 10 000 000.
Solution
In order to fix this we need to cast value to string and then to number.
%dw 2.0
output application/json
---
{
total: ((payload.price * payload.quantity) * (1-payload.discount/100)) as String as Number
}
As you can see we need to cast two times. The most important is casting to String as then our number is converted to standard notation. This works for DataWeave 2. For DataWeave 1 we need to format string as well, like below:
%dw 1.0
%output application/json
---
{
total: ((payload.price * payload.quantity) * (1-payload.discount/100)) as :string {format: "#"} as :number
}
After I have cast exponential numbers to a string I have applied format. For both versions, the next cast as the number is necessary when we want to avoid quotation marks around the string. How format works is quite nicely described in the following article.
Summary
In order to avoid sending numbers as exponential ones, casting to string and number is necessary. This problem occurs due to the fact that DataWeave is using one data type for storing different types of numbers and for preserving number precision.
Thank you, this is good info. I did actually come across this scenario recently and found the output representation a bit odd. Now I know how to make my code more readable.
Excellent article on this problem of 1 Number datatype.