Gson Builder — Special Values of Floats & Doubles

In our last Gson blog post we've looked at the option to make the JSON conversion lenient. Lenient allows the incoming JSON to be non-standard to some extend and Gson will still be able to parse it to Java objects. In this blog post we'll look at a case of allowing non-standard inputs: special values of Floats and Doubles (like Float.NEGATIVE_INFINITY).

Of course, this will not be the only post in our Gson series. If you're interested in the other topics, check out our series outline:

Gson Series Overview

Special Values of Floats/Doubles

In Java there is a need to express some edge cases with float and double values. Thus, the constants for Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY and Float.NaN and their double counterparts have been in the Java language since the beginning. Unfortunately, the JSON specification doesn't see the worth of those edge value and did not make it part of the specification.

Let's quote the Gson documentation on this issue:

Section 2.4 of JSON specification disallows special double values (NaN, Infinity, -Infinity). However, Javascript specification (see section 4.3.20, 4.3.22, 4.3.23) allows these values as valid Javascript values. Moreover, most JavaScript engines will accept these special values in JSON without problem. So, at a practical level, it makes sense to accept these values as valid JSON even though JSON specification disallows them.

Remember in our lenient blog post we wrote that when it comes to the JSON standard Gson is pretty flexible during deserialization and very strict during serialization? The first part is still true, but this float/double special values topic is the only exception where Gson can intentionally violate the standard.

Let's make it clear: if the incoming JSON uses one or more of those special float/double edge values, it'll deserialize it by default without any problems.

If you pass a Float.POSITIVE_INFINITY as a value, Gson will throw an exception because it cannot convert this and being compliant to the standard. If you require these value to be passed, you need to specifically enable the conversion of those using the GsonBuilder. Gson offers the method serializeSpecialFloatingPointValues() to do so.

It's time to look at an example. We created a user class which also stores a float value describing the weight.

public class UserFloat {  
    String name;
    Float weight;

    public UserFloat(String name, Float weight) {
        this.name = name;
        this.weight = weight;
    }
}

Now, the easter chocolate bunnies are having a negative effect on me and I've gained a lot of weight lately, so I'll need to create my user instance like this:

UserFloat user = new UserFloat("Norman", Float.POSITIVE_INFINITY);  

If you pass this to Gson, it'll throw an exception:

Gson gson = new Gson();

UserFloat user = new UserFloat("Norman", Float.POSITIVE_INFINITY);

String usersJson = gson.toJson(user); // will throw an exception  

Gson will give you an IllegalArgumentException, which will state

Infinity is not a valid double value as per JSON specification. To override this behavior, use GsonBuilder.serializeSpecialFloatingPointValues() method.`

The exception message is helpful and already pushes us to the solution. We need to utilize the GsonBuilder:

Float.POSITIVE_INFINITY

This will create a usersJson without any exception and the correct content:

GsonBuilder

Of course, since this isn't 100% standard you need to make sure your API can handle these unusual values.

Outlook

In this blog post, you've learned how Gson handles non-standard JSON float values. By default, Gson doesn't allow the serialization of edge values. Nevertheless, you can enable it with the GsonBuilder.

In the next blog post, we'll look at versioning your models.

If you've feedback or a question, let us know in the comments or on twitter @futurestud_io.

Make it rock & enjoy coding!

Explore the Library

Find interesting tutorials and solutions for your problems.