Core Java

Moshi BigDecimal requires explicit JsonAdapter

When working with JSON in Java, handling numerical data with precision is crucial, especially in financial applications. The BigDecimal class in Java provides arbitrary-precision arithmetic, which makes it an ideal choice for such scenarios. However, the popular JSON library Moshi does not natively support BigDecimal. Let us delve into understanding why Moshi BigDecimal parsing requires an explicit JSONadapter and how to implement that.

1. Introduction

Moshi is a modern JSON library for Android and Java that makes it easy to parse JSON into Java objects and serialize Java objects into JSON. Developed by Square, Moshi is designed to be simple, efficient, and flexible, making it a popular choice for developers working on Android applications or any Java-based projects. Key Features of Moshi are:

  • Easy to use: Moshi provides a simple API that makes it easy to parse and write JSON. The library leverages Java’s type system to ensure type safety.
  • Annotations: Moshi supports annotations to customize the serialization and deserialization processes. For example, you can use @Json to map JSON fields to Java fields with different names.
  • Adapters: Moshi allows you to create custom adapters to handle complex types or special serialization logic.
  • Reflection and Code Generation: By default, Moshi uses reflection to inspect your classes at runtime, but it also supports code generation for better performance and smaller APK sizes.
  • Interoperability with Kotlin: Moshi has excellent support for Kotlin, including Kotlin-specific features like data classes and default parameter values.

2. Handling BigDecimal in JSON with Moshi

2.1 BigDecimal Requires Explicit JsonAdapter

By default, Moshi does not support the BigDecimal type out of the box. When working with financial or precise numerical data, BigDecimal is often preferred over double due to its precision. To serialize and deserialize BigDecimal with Moshi, you need to create a custom JsonAdapter.

Here is a simple example of how to create a custom JsonAdapter for BigDecimal:

package com.jcg.example; 

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonReader;
import com.squareup.moshi.JsonWriter;

import java.io.IOException;
import java.math.BigDecimal;

public class BigDecimalJsonAdapter extends JsonAdapter<BigDecimal> {

    @Override
    public BigDecimal fromJson(JsonReader reader) throws IOException {
        String value = reader.nextString();
        return new BigDecimal(value);
    }

    @Override
    public void toJson(JsonWriter writer, BigDecimal value) throws IOException {
        writer.value(value.toString());
    }
}

This custom JsonAdapter converts BigDecimal to and from JSON. When deserializing, it reads the string value and converts it to a BigDecimal object. When serializing, it converts the BigDecimal object to its string representation.

2.2 Make Moshi Support BigDecimal

To use the custom BigDecimalJsonAdapter, you need to register it with Moshi. This can be done by creating a custom Moshi instance and adding the adapter to it.

To begin with, add the dependency to your project:

<dependency>
    <groupId>com.squareup.moshi</groupId>
    <artifactId>moshi-java8</artifactId>
    <version>jar_version</version>
</dependency>

2.2.1 Code Example: Registering the Custom JsonAdapter

Here is a simple example to register the Custom JsonAdapter:

import com.squareup.moshi.Moshi;

public class MoshiConfiguration {
    public static Moshi provideMoshi() {
        return new Moshi.Builder()
                .add(new BigDecimalJsonAdapter())
                .build();
    }
}

In this example, a custom Moshi instance is created with the BigDecimalJsonAdapter added to it. Now, whenever Moshi encounters a BigDecimal field, it will use this adapter to handle it.

2.2.2 Code Example: Using the Custom Moshi Instance

The below example demonstrates serializing a BigDecimal object to JSON and deserializing a JSON string back to a BigDecimal object using the custom Moshi instance.

package com.jcg.example; 

import com.squareup.moshi.JsonAdapter;

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        Moshi moshi = MoshiConfiguration.provideMoshi();
        JsonAdapter<BigDecimal> adapter = moshi.adapter(BigDecimal.class);

        // Serializing BigDecimal to JSON
        BigDecimal bigDecimalValue = new BigDecimal("12345.6789");
        String json = adapter.toJson(bigDecimalValue);
        System.out.println("Serialized JSON: " + json);

        // Deserializing JSON to BigDecimal
        String jsonInput = "\"12345.6789\"";
        BigDecimal deserializedValue = adapter.fromJson(jsonInput);
        System.out.println("Deserialized BigDecimal: " + deserializedValue);
    }
}

The code output is:

Serialized JSON: "12345.6789"
Deserialized BigDecimal: 12345.6789

3. Conclusion

While Moshi does not natively support BigDecimal, you can easily extend its functionality by creating a custom JsonAdapter. By registering this adapter with Moshi, you can seamlessly serialize and deserialize BigDecimal objects, ensuring your applications can handle precise numerical data effectively.

Yatin Batra

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button