DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Jackson vs Gson: Edge Cases in JSON Parsing for Java Apps
  • The Configure() Method in Jackson in JSON
  • Easy Mapping JSON to Java Objects Using Jackson
  • Streamlining Event Data in Event-Driven Ansible

Trending

  • Distributed Consensus: Paxos vs. Raft and Modern Implementations
  • Optimizing Serverless Computing with AWS Lambda Layers and CloudFormation
  • Useful System Table Queries in Relational Databases
  • Bridging UI, DevOps, and AI: A Full-Stack Engineer’s Approach to Resilient Systems
  1. DZone
  2. Coding
  3. Languages
  4. Micronaut Mastery: Decode JSON Using Custom Constructor Without Jackson Annotations

Micronaut Mastery: Decode JSON Using Custom Constructor Without Jackson Annotations

Let's take a look at how to decode JSON in Micronaut without the need for Jackson annotations.

By 
Hubert Klein Ikkink user avatar
Hubert Klein Ikkink
·
Aug. 20, 18 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
10.8K Views

Join the DZone community and get the full member experience.

Join For Free

Micronaut uses Jackson to encode objects to JSON and decode JSON to objects. Micronaut adds a Jackson ObjectMapper bean to the application context with all configuration to work properly. Jackson can by default populate an object with values from JSON as the class has a no argument constructor and the properties can be accessed. But if our class doesn't have a no argument constructor we need to use the @JsonCreator and @JsonProperty annotations to help Jackson. We can use these annotations on the constructor with arguments that is used to create an object.

But we can even make it work without the extra annotations, so our classes are easier to read and better reusable. We need to add the Jackson ParameterNamesModule as a module to the ObjectMapper instance in our application. And we need to compile our sources with the -parameter argument, so the argument names are preserved in the compiled code. Luckily the -parameter option is already added to our Gradle build when we create a Micronaut application. All we have to do is to add the ParameterNamesModule in our application.

We need to add a dependency on com.fasterxml.jackson.module:jackson-module-parameter-names to our compile classpath. Micronaut will automatically find the ParameterNamesModule and add it to the ObjectMapper using the findAndRegisterModules method.

So we change our build.gradle file first:

// File: build.gradle
...
dependencies {
    ...
    compile "com.fasterxml.jackson.module:jackson-module-parameter-names:2.9.0"
    ...
}
...

In our application we have the following class that has an argument constructor to create an immutable object:

package mrhaki;

import java.util.Objects;

public class Language {
    private final String name;

    private final String platform;

    public Language(final String name, final String platform) {
        this.name = name;
        this.platform = platform;
    }

    public String getName() {
        return name;
    }

    public String getPlatform() {
        return platform;
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) { return true; }
        if (o == null || getClass() != o.getClass()) { return false; }
        final Language language = (Language) o;
        return Objects.equals(name, language.name) &&
                Objects.equals(platform, language.platform);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, platform);
    }
}

We write the following sample controller to use the Language class as a return type (we wrap it in a Mono object so the method is reactive):

package mrhaki;

import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import reactor.core.publisher.Mono;

@Controller("/languages")
public class LanguagesController {

    @Get("/groovy")
    public Mono<Language> getGroovy() {
        return Mono.just(new Language("Groovy", "JVM"));
    }

}

And in our test, we use HttpClient to invoke the controller method. The exchange method will trigger a decode of the JSON output of the controller to a Language object:

package mrhaki

import io.micronaut.context.ApplicationContext
import io.micronaut.http.HttpRequest
import io.micronaut.http.HttpStatus
import io.micronaut.http.client.HttpClient
import io.micronaut.runtime.server.EmbeddedServer
import spock.lang.AutoCleanup
import spock.lang.Shared
import spock.lang.Specification

class LanguagesControllerSpec extends Specification {

    @AutoCleanup
    @Shared
    private static EmbeddedServer server = ApplicationContext.run(EmbeddedServer)

    @AutoCleanup
    @Shared
    private static HttpClient client = server.applicationContext.createBean(HttpClient, server.URL)

    void '/languages/groovy should find language Groovy'() {
        given:
        final request = HttpRequest.GET('/languages/groovy')

        when:
        final response = client.toBlocking().exchange(request, Language)

        then:
        response.status() == HttpStatus.OK

        and:
        response.body() == new Language('Groovy', 'JVM')
    }


}

When we wouldn't have the dependency on jackson-module-parameter-names and not use the -parameter compiler option we get the following error message:

[nioEventLoopGroup-1-6] WARN  i.n.channel.DefaultChannelPipeline - An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
io.micronaut.http.codec.CodecException: Error decoding JSON stream for type [class mrhaki.Language]: Cannot construct instance of `hello.conf.Language` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (byte[])"{"name":"Groovy","platform":"JVM"}"; line: 1, column: 2]

But with the dependency and -parameter compiler option we have a valid test without any errors. Jackson knows how to use the argument constructor to create a new Language object.

Written with Micronaut 1.0.0.M4.

JSON Jackson (API) Annotation

Published at DZone with permission of Hubert Klein Ikkink, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Jackson vs Gson: Edge Cases in JSON Parsing for Java Apps
  • The Configure() Method in Jackson in JSON
  • Easy Mapping JSON to Java Objects Using Jackson
  • Streamlining Event Data in Event-Driven Ansible

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!