Friday, July 24, 2015

Getting different objects from Jackson

Hello All, today I want to explain you a special case when we want to get different objects from Jackson Library.

What is Jackson API and how it works?
     It is a standard JSON library for Java (or JVM platform in general), or, as the "best JSON parser for Java". Or simply as "JSON for Java". It is very useful and flexiblt in nature. It takes JSON string in to consideration and changes it to Java object or vice versa.

What is a JSON string?
    JSON is a special format of representing the data in a string format, you can think it as a refined version of XML.

Eg:
    In XML:
        <user>
            <author>Ankur</author>
            <name>Codepool</name>
         </user>
    In JSON:
        user:{
                "author" : "Ankur",
                "name" : "Codepool",
        }
     

Now before going further lets us take a basic example of how Jackson works to and forth?

User.java
public class User {
    private String name;
    private String author;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    @Override
    public String toString() {
        return "User [name=" + name + ", author=" + author + "]";
    }
}

ExampleJackson.java
public class ExampleJackson {
    public static void main(String[] args) throws Exception {
        User user = new User();
            user.setName("Ankur");
            user.setAuthor("Codepool");

        //Writing a Java object as a Json String
        ObjectMapper objectMapper = new ObjectMapper();
        System.out.println(objectMapper.writeValueAsString(user));
        //Output: {"name":"Ankur","author":"Codepool"}

        //Now reading from Json string to Java object
        String jsonString = "{\"name\":\"NewAnkur\", \"author\":\"NewAuthor\" }";
        User newUser = objectMapper.readValue(jsonString, User.class);
        System.out.println(newUser);
        //Output: User [name=NewAnkur, author=NewAuthor]
    }
}

Now let us take a case, where we want to get the object on the basis of data inside the JSON string, that means if the name value is Ankur, I want AnkurUser object and if name value is John, we want the JohnUser object.

For this type of functionality we have the annotations defined in Jackson library, those are :
  • @JsonTypeInfo
  • @JsonSubTypes
  • @JsonSubTypes.Type
Now lets edit the User class in a way like this:

User.java
@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "name", // (A)
    visible = true  // (B)
)
@JsonSubTypes( {
    @JsonSubTypes.Type(name = "ankur", value = AnkurUser.class), //(C)
    @JsonSubTypes.Type(name = "john", value = JohnUser.class)  //(D)
})
abstract class User {
    private String name;
    private String author;
    protected abstract void show();

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    @Override
    public String toString() {
        return "User [name=" + name + ", author=" + author + "]";
    }
}

AnkurUser.java
class AnkurUser extends User{

 public AnkurUser(){
   System.out.println("Ankur Created");
  }
  @Override
 protected void show() {
  System.out.println("This is ankur user");
 }

 @Override
  public String toString() {
   return "AnkurUser [name=" + super.getName() + ", author=" + super.getAuthor() + "]";
  }
}

JohnUser.java
class JohnUser extends User {
    public AnkurUser() {
        System.out.println("Ankur Created");
    }
    @Override protected void show() {
        System.out.println("This is john user");
    }
    @Override
    public String toString() {
        return "JohnUser [name=" + super.getName() + ", author=" + super.getAuthor() + "]";
    }
}
Now lets see the usage and output:

ExampleJackson .java
public class ExampleJackson {
    public static void main(String[] args) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();

        //Now reading from Json string to Java object
        String jsonString = "{\"name\":\"ankur\", \"author\":\"NewAuthor\" }";
        User newUser = objectMapper.readValue(jsonString, User.class);
        newUser.show();
        /*
        * Output: (E)
        *  Ankur Created
        *  This is ankur user
        */
    }
}

If you notice the equation (C) tells you that the object that is created, is of AnkurUser class and returns you the same, this transition is because of the annotation configuration that we did at the creation of the User class, which says check for the property named name (equation (A)), and if its value is Ankur  create the AnkurUser object and so on, at equation (C) and (D). The equation (B) states that the field is also going to be visible for further calls  normally the field that is used as a deciding factor of the object, is never visible for further manipulations.

Thanks

No comments:

Post a Comment