Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return BigDecimal fields as JSON String values in Java

I have a Get API which returns a JSON. The format expected is:

{
   "value1": "123.00",
   "value2": "23.00"
}

These values are BigDecimal in the object:

public class Result{
    BigDecimal value1;
    BigDecimal value2;
    // getters and setters
}

Now, when the request is made, I create the Result object and populate these values as BigDecimal, create a list and return. The response I received is:

{
   "value1": 123.00,
   "value2": 23.00
}

The values are correct but are not strings. How can I make them strings?

I know we can convert BigDecimal to String but I have object with BigDecimal fields only and I can't populate String values to it.

Finally, this is how the list is made:

List<MyObj> obj = Arrays.stream(myObj).collect(Collectors.toList());

    Result result = new Result();

    obj.forEach(t -> t.mergeToResult(result));  // mergeToResults does all the population like result.setValue1(new BigDecimal(123.00))

    return result;
like image 823
roger_that Avatar asked Sep 03 '18 12:09

roger_that


2 Answers

You can use @JsonFormat annotation as below:

import com.fasterxml.jackson.annotation.JsonFormat;

public class Result {        
   @JsonFormat(shape = JsonFormat.Shape.STRING)
   private BigDecimal value;

   // getters and setters
}
like image 58
Pawan Kumar Avatar answered Nov 04 '22 17:11

Pawan Kumar


Use String

The Number type in JSON is likely to be considered as a floating-point number, from my reading of the Wikipedia page, per the traditional behavior of JavaScript. Floating-point technology purposely sacrifices accuracy for the sake of execution speed.

The BigDecimal class has exactly the opposite purpose, to sacrifice execution speed for the sake of accuracy.

So, if you want the best chance of preserving your BigDecimal value, store as a String. Hopefully this approach makes it less likely that the consumer of your JSON will inadvertently parse the incoming value as a floating-point. Clearly document to those people consuming your JSON about your intention to have the data parsed as a BigDecimal or equivalent rather than floating-point.

Java export:

String output = myBigDecimal.toString() ;

JSON:

{
   "value1": "123.00",
   "value2": "23.00"
}

Java import:

BigDecimal bd = new BigDecimal( "123.00" ) ;

Study the documentation for BigDecimal::toString and new BigDecimal( string ). You should also be aware of the BigDecimal::toPlainString method.

Streams

As for your Java streams, I do not understand your issue. You use of List and arrays is unexplained.

Basically, you should be implementing a toJson method on your Result class. Call that Result::toJson method within your stream code.

Here is an example of such a class.

package com.basilbourque.example;

import java.math.BigDecimal;

public class Result {

    BigDecimal start, stop;

    public String toJson () {
        StringBuilder sb = new StringBuilder( "{\n" );
        sb.append( "    " );  // Indent with four spaces.
        sb.append( this.enquote( "start:" ) + " " );
        sb.append( this.enquote( start.toString() ) );
        sb.append( " , \n" );
        sb.append( "    " );  // Indent with four spaces.
        sb.append( this.enquote( "stop:" ) + " " );
        sb.append( this.enquote( stop.toString() ) );
        sb.append( "\n}\n" );
        return sb.toString();
    }

    static public Result fromJson ( String json ) {
         …
    }

    private String enquote ( String string ) {
        return "\"" + string + "\"";
    }

    // Constructor
    public Result ( BigDecimal start , BigDecimal stop ) {
        this.start = start;
        this.stop = stop;
    }

    public static void main ( String[] args ) {
        Result r = new Result( new BigDecimal( "123.00" ) , new BigDecimal( "23.00" ) );
        System.out.println( r.toJson() );
    }
}

When run.

{
    "start:" "123.00" , 
    "stop:" "23.00"
}

Consider a framework

Tip: You may want to consider using a JSON↔Java mapping framework to help you with this work.

like image 3
Basil Bourque Avatar answered Nov 04 '22 18:11

Basil Bourque