DEV Community

Jitendra Singh Bisht
Jitendra Singh Bisht

Posted on • Originally published at jsblogs.github.io on

3

Deserialize json with Java parameterized constructor

Hi Guys in my previous blog JSON deserialize generic types using Gson and Jackson I talked about how you can deserialize json in Java Generics. Now in this blog post we are going to learn how to deserialize json into Java class which doesn’t have default constructor. For this blog I am using Jackson library.

Almost all frameworks requires default/no-argument constructor in your class. Because these frameworks use reflection to create objects by invoking default constructor. But if there is no default constructor present in class then its hard to instantiate using reflection. Let’s assume we have a class with no-args constructor (only a parameterized constructor present) and we want to deserialize it.

package samples.jackson;
/**
* @author Jitendra Singh.
*/
public class UserProfile {
private String name;
private String profilePicture;
private String email;
public UserProfile(String name, String profilePicture, String email) {
this.name = name;
this.profilePicture = profilePicture;
this.email = email;
}
public String getName() {
return name;
}
public String getProfilePicture() {
return profilePicture;
}
public String getEmail() {
return email;
}
}

And a json file

{
"name": "Dummy",
"profilePicture": "http://picturesource",
"email": "dummy@myblogspro.com"
}

There are two ways in Jackson to deserialize this type of classes.

  1. Custom deserializer
  2. Mixin Annotations

1. Custom Deserializer

In Custom Deserializer you will create a class and extend it with com.fasterxml.jackson.databind.JsonDeserializer and override its abstract method deserialize(). This class gives you full control, you’ll get json in com.fasterxml.jackson.core.JsonParser. Now you can map json properties with class properties. In my case I am creating UserProfileDeserializer.

package samples.jackson;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
/**
* @author Jitendra Singh.
*/
public class UserProfileDeserializer extends JsonDeserializer<UserProfile> {
@Override
public UserProfile deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
String EMPTY_STRING = "";
JsonNode node = p.readValueAsTree();
String name = node.has("name") ? node.get("name").asText() : EMPTY_STRING;
String profilePic = node.has("profilePicture") ? node.get("profilePicture").asText() : EMPTY_STRING;
String email = node.has("email") ? node.get("email").asText() : EMPTY_STRING;
return new UserProfile(name, profilePic, email);
}
}

Now we need to register above deserializer in com.fasterxml.jackson.databind.ObjectMapper. So that, while deserializing UserProfile class it use UserProfileDeserializer.

package samples.jackson;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.io.IOException;
/**
* @author Jitendra Singh.
*/
public class UserProfileDeserializerDemo {
public static void main(String[] args) throws IOException {
// MyBlogsPro is just module name. You can choose your own name
SimpleModule module = new SimpleModule("MyBlogsPro");
module.addDeserializer(UserProfile.class, new UserProfileDeserializer());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
// TODO: 12/9/16 Pass your json string/source as first parameter in below method
UserProfile profile = mapper.readValue("{}", UserProfile.class);
}
}

In above code we are adding our Deserializer in com.fasterxml.jackson.databind.module.SimpleModule and that module is registered in com.fasterxml.jackson.databind.ObjectMapper. Similarly, you can register deserializers for other classes too.

2. Mixin Annotations

Jackson provides another way of doing this by using _ Mixin Annotations _. You can read about Jackson Mixin here. In our class UserProfile there is no default constructor, it has a parameterized constructor. Let’s checkout how to create mixin for our class.

package samples.jackson;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* @author Jitendra Singh.
*/
public abstract class UserProfileMixin {
@JsonCreator
public UserProfileMixin(@JsonProperty("name") String name, @JsonProperty("profilePicture") String profilePicture,
@JsonProperty("email") String email) {
}
}

That’s it !!

We have created a constructor same as in UserProfile class and marked it with com.fasterxml.jackson.annotation.JsonCreator annotation. This will tell com.fasterxml.jackson.databind.ObjectMapper this is how target class (UserProfile) constructor looks and constructor parameters are marked with com.fasterxml.jackson.annotation.JsonProperty annotation.

Now checkout how to register this mixin class in com.fasterxml.jackson.databind.ObjectMapper

package samples.jackson;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.io.IOException;
/**
* @author Jitendra Singh.
*/
public class UserProfileMixinDemo {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(UserProfile.class, UserProfileMixin.class);
// TODO: 12/9/16 Pass your json string/source as first parameter in below method
UserProfile profile = mapper.readValue("{}", UserProfile.class);
}
}

Enjoy !!!! ☺☺

Top comments (0)