2

I am created a rest API in spring boot which consumes third party API response and return the response.

Challenges : Third party API response {"price":123456789123456789123456789.05}

I want to get the "price" from the single object ,So it will return 123456789123456789123456789.05 as expected

Expected Output : 123456789123456789123456789.05

Actual Output : 1.2345678912345679e+26

Note:

The actual output will given as exponential format but i want actual data without exponential.

Code: pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>sample</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sample</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- tag::actuator[] -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- end::actuator[] -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple -->
        <dependency>
            <groupId>com.googlecode.json-simple</groupId>
            <artifactId>json-simple</artifactId>
            <version>1.1</version>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

SampleApplication.java

package com.example.sample;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;


@SpringBootApplication
public class SampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(SampleApplication.class, args);
    }

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

HelloController.java

package com.example.sample;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

@RestController
public class HelloController {
 @Autowired
 RestTemplate restTemplate;

 @RequestMapping("/")
 public double index() throws Exception {
  HttpHeaders headers = new HttpHeaders();
  headers.set("token", "rtp");
  HttpEntity entity = new HttpEntity < String > ("parameters", headers);
  String END_Point_Test_API = "http://localhost:8080/api/test";
  ResponseEntity < String > responseData = restTemplate.exchange(END_Point_Test_API, HttpMethod.GET, entity, String.class);
  //Third party response {"price":123456789123456789123456789.05}
  System.out.println(responseData.getBody());
  String data = responseData.getBody();

  JSONParser parser = new JSONParser();
  JSONObject jsobj = (JSONObject) parser.parse(data);
  //double price =(double)jsobj.get("price");
  double price = Double.parseDouble(String.valueOf(jsobj.get("price")));
  return price;

 }

}
siva
  • 593
  • 3
  • 8
  • 19
  • 1
    Possible duplicate of [Java BigDecimal without E](https://stackoverflow.com/questions/12026610/java-bigdecimal-without-e) – adickinson Mar 21 '19 at 10:15
  • @adickinson no. That link has nothing to do with reading JSON input. And even less with doing so from Spring Boot automatic JSON parser. – kumesana Mar 21 '19 at 10:40
  • @kumesana "The actual output will given as exponential format but i want actual data without exponential." The problem appears to be formatting, not reading the value itself as the OP has already managed that part. The link is relevant. – adickinson Mar 21 '19 at 10:48
  • @adickinson you can't format data you don't have. To do what's OP is asking, the number needs to be read and contain exactly the same information as the JSON contains. That's not the typical behavior, and this is what needs to be addressed. As OP noticed, the number needs to be read as BigDecimal or some other helpful feature to achieve the requirement. – kumesana Mar 21 '19 at 10:51
  • @kumesana Unless I'm missing something, OP does have that data, they retrieve and return it, but it is outputted in exponent format, which they do not want. The value itself will be correct in the JVM, but it is incorrectly formatted for their purpose. – adickinson Mar 21 '19 at 10:58
  • You have some problem on concept. Please check bellow link about decimal format https://stackoverflow.com/a/39150483/3073945 – Md. Sajedul Karim Mar 21 '19 at 11:59
  • @adickinson you're missing that a double can't contain that many digits – kumesana Mar 21 '19 at 12:15

2 Answers2

2

The correct way to convert BigDecimal to double is:

((BigDecimal) jsobj.get("price")).doubleValue()

However, you are converting BigDecimal to double. Double has a vast range, but even this range has limits. When you exceed it you will run into conversion problems.

My suggested answer is, do not convert it to double use BigDecimal for your price.

Dimitris
  • 560
  • 3
  • 17
  • Above example is not working and In case we can use BigDecimal but the response will came from third part API so its a static one.So kindly give the exact solution for that. – siva Mar 21 '19 at 11:15
  • if it does not work then probably it needs casting like I commented `((BigDecimal) jsobj.get("price")).doubleValue()`. My suggested answer remains the same you parse the incoming value to double, do not do that change your price type to BigDecimal. – Dimitris Mar 21 '19 at 11:30
  • Right now you read an Object (holding the BigDecimal), you are converting the Object to String and then convert the String to double. – Dimitris Mar 21 '19 at 11:31
  • kindly share me the small snippet of code by using BigDecimal. – siva Mar 21 '19 at 11:34
  • You will also need to adjust the return type of your method to BigDecimal, but this is it: `BigDecimal price = (BigDecimal) jsobj.get("price"); return BigDecimal;` – Dimitris Mar 21 '19 at 11:39
  • @siva I am getting a bit lost as to what you want, if you just want to print the value of the BigDecimal as String in the front end just change the method to return String and do `return ((BigDecimal) jsobj.get("price")).toString();` – Dimitris Mar 21 '19 at 11:47
  • Why do you believe that anything is parsed as a BigDecimal? – kumesana Mar 21 '19 at 12:18
  • @kumesana Because that is what the title says "How to retrieve big decimal value[...]" – Dimitris Mar 21 '19 at 13:04
  • @Dimitris sounds to me then, like they're asking how to do it, not assuming that it is already done. – kumesana Mar 21 '19 at 13:05
  • @kumesana The question is only regarding the format, the OP does not want the E notation. I cannot reproduce with the code provided, so I just made my best answer from the provided information. – Dimitris Mar 21 '19 at 13:17
  • @Dimitris Still problem not solved I changed my code as like what you are suggested : BigDecimal price= (BigDecimal) jsobj.get("price"); return price; (the return type will be BigDecimal ) but issue return as "java.lang.Double cannot be cast to java.math.BigDecimal" – siva Mar 26 '19 at 06:43
0

To make it clear: as soon as double is used, you have an approximation of the actual value, without defined precision and everything will just be some imperfect repair.

BigDecimal price = (BigDecimal) jsobj.get("price");
System.out.println(price.toPlainString());

This is probably also mentioned in the provided links. toPlainString will avoid using the scientific E-notation.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138