Giter Site home page Giter Site logo

When using jslt function number() and passing string with big decimal for eg "180000000000" returns scientifc/exponential notation about jslt HOT 13 CLOSED

jugup avatar jugup commented on June 13, 2024
When using jslt function number() and passing string with big decimal for eg "180000000000" returns scientifc/exponential notation

from jslt.

Comments (13)

larsga avatar larsga commented on June 13, 2024 1

It doesn't help to tell Jackson not to use DoubleNode, because that's what JSLT uses internally. I didn't want to use BigDecimal internally for performance reasons.

But if your consumer uses a JSON parser that can't read 1.8E7 then ... well ... it's a part of JSON, so their JSON parser is broken.

from jslt.

larsga avatar larsga commented on June 13, 2024

I assume it's the last line here,

output = mapper.writeValueAsString(transformedData);

where the number becomes "1.8E7"? If so, this is not a JSLT question, since JSLT is returning a JsonNode with a decimal number in it. The choice to represent it as "1.8E7" in string form is made by Jackson, not JSLT. I don't think it's possible to modify JSLT (or your JSLT code) to change that.

from jslt.

jugup avatar jugup commented on June 13, 2024

If its jackson, wouldnt {"amount": 18000000.00000} also give out the exponential result, but instead it works fine, but not when {"amount": "18000000.00000"}

and we have our Jackson mapper to not use scientific notation

from jslt.

larsga avatar larsga commented on June 13, 2024

I agree it's strange that Jackson does not appear to be obeying your settings, but to see why I think this has nothing to do with JSLT, try running the code like this:

            JsonNode transformedData;
            JsonNode inputJson = mapper.readTree("18000000.00000");
            output = mapper.writeValueAsString(inputJson);

You should still get "1.8E7", even with no JSLT involved at all.

from jslt.

jugup avatar jugup commented on June 13, 2024

Tried the code, and we are getting expected result
18000000.00000

from jslt.

jugup avatar jugup commented on June 13, 2024

So it does seem that the number() function is converting it into scientific notation

from jslt.

larsga avatar larsga commented on June 13, 2024

Nope.

This code:

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.schibsted.spt.data.jslt.Parser;
import com.schibsted.spt.data.jslt.Expression;
import com.schibsted.spt.data.jslt.impl.ExpressionImpl;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonGenerator.Feature;

public class Test {

  public static void main(String[] args) throws Exception {
    // Create mapper for parsing
    ObjectMapper mapper = new ObjectMapper().enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)
      .setNodeFactory(JsonNodeFactory.withExactBigDecimals(true))
      .enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);

    // Enable features to handle long decimal values rather than
    // converting them in exponential format
    mapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
    mapper.enable(Feature.WRITE_BIGDECIMAL_AS_PLAIN);

    // Initialize data and mapping
    JsonNode inputJson = mapper.readTree("18000000.00000");
    //JsonNode transformedData = template.apply(inputJson);
    String output = mapper.writeValueAsString(inputJson);
    System.out.println("output: " + output);
  }
}

produces:

MacBook-Pro-3:tmp larsga$ java Test
output: 18000000.00000

from jslt.

jugup avatar jugup commented on June 13, 2024

Hello @larsga, as you have also tried the code, when you do

    // Initialize data and mapping
    JsonNode inputJson = mapper.readTree("18000000.00000");
    //JsonNode transformedData = template.apply(inputJson);
    String output = mapper.writeValueAsString(inputJson);
    System.out.println("output: " + output);

it outputs 18000000.00000 but initially you mentioned it would return 1.8E7.

I think there is some confusion. Maybe we can go over the problem statement again.

  1. While parsing big numbers using jackson and Feature.WRITE_BIGDECIMAL_AS_PLAIN it does not scientific/exponential result, number is in plain text.
  2. When use JSLT with number() function and parse the big number, returned out put is in scientific/exponential notation. Which we think is unexpected because without JSLT just with jackson it works fine (as tried by both of us), maybe the function is causing some issues?

from jslt.

larsga avatar larsga commented on June 13, 2024

You're right, of course, I was too quick there. Sorry.

The test above showed that when JSLT is not used, Jackson gives the correct output. Your claim is that putting the string through the number() function somehow changes that. So let's test that, too.

I get the same result as you: output: 1.8E7. OK, so something is going on in Jackson.

This code:

    // Initialize data and mapping
    JsonNode inputJson = mapper.readTree("18000000.00000");
    System.out.println("" + inputJson + " " + inputJson.getClass());

    inputJson = mapper.readTree("\"18000000.00000\"");
    JsonNode transformedData = template.apply(inputJson);
    String output = mapper.writeValueAsString(transformedData);
    System.out.println("" + transformedData + " " + transformedData.getClass());

produces:

18000000.00000 class com.fasterxml.jackson.databind.node.DecimalNode
1.8E7 class com.fasterxml.jackson.databind.node.DoubleNode

So the problem here is that Jackson is serializing DecimalNode in a different way from DoubleNode.

Note that what you are having problems with is the string representation of the number, but JSLT is returning DoubleNode; that is, a number, not a string. So the problem is still how Jackson converts the number to a string. It's not JSLT that's producing the string, but Jackson.

You've set WRITE_BIGDECIMAL_AS_PLAIN, but this isn't a BIgDecimal, but rather a DoubleNode. If you convert the node to a DecimalNode the problem goes away. Add this line at the end:

    System.out.println("" + DecimalNode.valueOf(transformedData.decimalValue()));

and you get:

18000000.00000 class com.fasterxml.jackson.databind.node.DecimalNode
1.8E7 class com.fasterxml.jackson.databind.node.DoubleNode
1.8E+7

from jslt.

larsga avatar larsga commented on June 13, 2024

Sorry. Still too quick. I'm in a rush here.

Last line:

    System.out.println(mapper.writeValueAsString(DecimalNode.valueOf(transformedData.decimalValue())));

Output:

18000000.00000 class com.fasterxml.jackson.databind.node.DecimalNode
1.8E7 class com.fasterxml.jackson.databind.node.DoubleNode
18000000

from jslt.

jugup avatar jugup commented on June 13, 2024

Yeah, was able to reproduce the same outcome. Tried out following seting on mapper to not use DoubleNode

            ObjectMapper mapper = new ObjectMapper().enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)
                    .setNodeFactory(JsonNodeFactory.withExactBigDecimals(true))
                    .configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true)
                    .configure(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS, true)
                    .configure(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN, true);

but still it doesnt work. Do you know any solution which can help us to overcome this issue?

from jslt.

larsga avatar larsga commented on June 13, 2024

I'm afraid I don't know of any way to change Jackson's behaviour here.

But I do have one question for you. Why do you care? It's a perfectly usable serialization of the number.

from jslt.

jugup avatar jugup commented on June 13, 2024

Yeah, i agree, it shouldnt have mattered so much, but have one cosumer who is not able to convert it back to actual number, will try to convence that this is how it is.

from jslt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.