1. Introduction
The Gson library developed by Google is quite a good choice for serialization and deserialization of Java objects to and from JSON format. Besides, we typically come across the problem that Gson shows integers as floating-point numbers while serializing objects.
In this tutorial, we’ll see why integers are considered floating-point numbers. Moreover, we’ll provide a solution to prevent Gson from doing that.
2. Problem Definition
Gson serializes Java objects to JSON. By default, Gson serializes integers as floating-point numbers for a more accurate representation. Here’s a simple example:
public String jsonString= "[{\"id\":4077395,\"field_id\":242566,\"body\":\"\"}, " +
"{\"id\":4077398,\"field_id\":242569,\"body\":[[273019,0],[273020,1],[273021,0]]}, " +
"{\"id\":4077399,\"field_id\":242570,\"body\":[[273022,0],[273023,1],[273024,0]]}]";
Here, we declared a JSON string called jsonString that represents an array of objects. This JSON array has different fields, such as id, field_id, and body.
Now, we’ll use the Gson library for JSON string deserialization into a list of Hashtable<String, Object> objects.
ArrayList<Hashtable<String, Object>> responses;
Type ResponseList = new TypeToken<ArrayList<Hashtable<String, Object>>>() {}.getType();
responses = new Gson().fromJson(jsonString, ResponseList);
Here, we declare an ArrayList named responses to contain elements of type Hashtable with String keys and Object values. Moreover, we utilize the Gson library for deserializing the jsonString into a list of Hashtables.
Finally, we use the TypeToken to get generic type information during deserialization.
The responses will be formatted as follows:
[{
body = ,
field_id = 242566.0,
id = 4077395.0
}, {
body = [
[273019.0, 0.0],
[273020.0, 1.0],
[273021.0, 0.0]
],
field_id = 242569.0,
id = 4077398.0
}, {
body = [
[273022.0, 0.0],
[273023.0, 1.0],
[273024.0, 0.0]
],
field_id = 242570.0,
id = 4077399.0
}]
Note that the Gson represents integers as floating-point numbers.
3. Default Number Strategy in Gson
Gson’s default number strategy aims to strike a balance between accuracy and flexibility when representing numeric values. The decision to use floating-point numbers for integers is based on the idea that JSON lacks explicit support for distinguishing between integer and floating-point types. Therefore, Gson opts for a default strategy that ensures the preservation of precision in numeric values.
However, this default behavior may not align with specific requirements or preferences, especially when dealing with scenarios where integers should remain integers in the JSON representation.
4. Using setObjectToNumberStrategy() Method
Using the Gson method setObjectToNumberStrategy(), we can thoroughly control the functionalities of the object-to-number conversion mechanism during the deserialization process.
Let’s explore this capability through an illustrative example:
public static String expectedOutput ="[{body=, field_id=242566, id=4077395}, " +
"{body=[[273019, 0], [273020, 1], [273021, 0]], field_id=242569, id=4077398}, " +
"{body=[[273022, 0], [273023, 1], [273024, 0]], field_id=242570, id=4077399}]";
@Test
public void givenJsonString_whenUsingsetObjectToNumberStrategyMethod_thenValidateOutput() {
Gson gson = new GsonBuilder()
.setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
.create();
ArrayList<Hashtable<String, Object>> responses = gson.fromJson(jsonString,
new TypeToken<ArrayList<Hashtable<String, Object>>>() {}.getType());
assertEquals(expectedOutput, responses.toString());
}
Here, the use of the setObjectToNumberStrategy() method enables us to set up a strategy such as ToNumberPolicy.LONG_OR_DOUBLE for Gson to direct its behavior in regard to numeric values. Finally, we verify the conversion process using the assertEquals() method.
Moreover, the ToNumberPolicy enum in Gson supports various strategies for handling numeric values. Besides ToNumberPolicy.LONG_OR_DOUBLE, which we used in the example, other strategies include:
- ToNumberPolicy.DOUBLE_ONLY: converts all numeric values to double during deserialization
- ToNumberPolicy.LONG_ONLY: converts all numeric values to long during deserialization
- ToNumberPolicy.DEFAULT: retains Gson’s default behavior, representing integers as floating-point numbers
5. Conclusion
In this article, we discuss an issue encountered with Gson: integers are automatically converted to floating-point numbers during the serialization process. To resolve this problem, we use the setObjectToNumberStrategy() method.
As always, the complete code samples for this article can be found over on GitHub.