Crickcoder
Crickcoder

Reputation: 2155

Parse json into multiple java pojos

I am writing a Restful webservice which would receive data in the below format.

{
  "myOrder": {
    "submitDate": "2015-04-16T02:52:01.406-04:00",
    "supplier": "Amazon",
    "orderName": "Wifi Router",
    "submittedBy": "Gaurav Varma",
    "price": {
      "value": "2000",
      "currency": "USD"
    },
    "address": {
      "name": "My home",
      "address": "Unknow island",
      "city": "Mainland China",
      "state": "Xinjiang",
      "contact": {
        "firstName": "Gaurav",
        "lastName": "Varma",
        "phone": "000-000-0000",
        "email": "[email protected]"
      }
    }
  }
}

To read that data I am considering Jackson or GSON frameworks. The easiest way would be to use a Java POJO which has exactly the same structure as the json request. But for me the structure of Java POJOs is different. I have four different pojo as mentioned below :

Submitter.java
 - SubmittedBy
 - SubmitDate
Order.java
 - Supplier
 - OrderName
Price.java
 - Value
 - Currency
Address.java
 - Name
 - Address
 - City
 - State
Contact.java
 - FirstName
 - LastName
 - Phone
 - Email

Question : Is it a way to parse the json once into five different POJOs. May be some annotation based approach where we can map json attribute to respective pojo attribute? Any framework available for it?

Thanks in advance !

Upvotes: 3

Views: 3939

Answers (5)

Crickcoder
Crickcoder

Reputation: 2155

I figured out the solution approach. Posting for other users. The complete implementation is on my blog - http://javareferencegv.blogspot.com/2015/04/parse-json-into-multiple-java-pojos.html

So basically 3 points regarding solution approach:

  1. We use Jackson annotation - @JsonIgnoreProperties. This would make sure only those fields in Pojo are mapped to JSON attributes. So we read the json twice, once mapping to Order.java and then to Submitter.java. Both gets the correspondingly mapped fields.
  2. We use Jackson annotation - @JsonProperty. This lets us map the exact JSON attribute to a field in POJO. The annotation makes sure different named attributes in JSON and POJO are mapped.
  3. Jackson doesn't provide any annotation to perform @JsonWrapped (The vice-versa @JsonUnwrapped is available for serialization). Hence, we map Price as an attribute in Order.java.

The main class looks like this :

import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonDeserializer {

    public static void main(String[] args) {
        try {
            // ObjectMapper provides functionality for data binding between
            ObjectMapper mapper = new ObjectMapper();

            String jsonString = "{\"submitDate\":\"2015-04-16\",\"submittedBy\":\"Gaurav Varma\",\"supplier\":\"Amazon\",\"orderName\":\"This is my order\"," 
                    + "\"price\": {\"value\": \"2000\",\"currency\": \"USD\"}"
                    + "}";
            System.out.println("JSON String: " + jsonString);

            // Deserialize JSON to java format and write to specific POJOs
            Submitter submitterObj = mapper.readValue(jsonString, Submitter.class);
            Order orderObj = mapper.readValue(jsonString, Order.class);
            Price priceObj = orderObj.getPrice();

            System.out.println("submitterObj: " + submitterObj);
            System.out.println("orderObj: " + orderObj);
            System.out.println("priceObj: " + priceObj);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

Upvotes: 1

You could use Jackson; I think you need a POJO to wrapp the Order and Address like

class FullOrder {
   Order order;
   Address address;

   public Order getOrder() {
        return order;
   }

   public void setOrder(Order order) {
       this.order = order;
   }

   public Address getAddress() {
       return address;
   }

   public void setAddress(Address address) {
      this.address = address;
   }

}

With this you can easily use Jackson

    String json; // your json here
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.readValue(json, FullOrder.class);

And that will parse the json into your pojo. Hope it helps you


The full structure

class Submitter {
    private Date submittedBy;
    private Date submitDate;

    public Date getSubmittedBy() {
     return SubmittedBy;
    }

    public void setSubmittedBy(Date submittedBy) {
     SubmittedBy = submittedBy;
    }

    public Date getSubmitDate() {
     return SubmitDate;
    }

    public void setSubmitDate(Date submitDate) {
     SubmitDate = submitDate;
    }

    }

    class Order {
    private String supplier;
    private String orderName;
    private Price price;
    private Submitter submitter;

    public Price getPrice() {
     return price;
    }

    public void setPrice(Price price) {
     this.price = price;
    }

    public Submitter getSubmitter() {
     return submitter;
    }

    public void setSubmitter(Submitter submitter) {
     this.submitter = submitter;
    }

    public String getSupplier() {
     return Supplier;
    }

    public void setSupplier(String supplier) {
     Supplier = supplier;
    }

    public String getOrderName() {
     return OrderName;
    }

    public void setOrderName(String orderName) {
     OrderName = orderName;
    }

}

class Price {
    private int value;
    private int currency;

    public int getValue() {
     return value;
    }

    public void setValue(int value) {
     this.value = value;
    }

    public int getCurrency() {
     return currency;
    }

    public void setCurrency(int currency) {
     this.currency = currency;
    }

}

class Address {
    private String name;
    private String address;
    private String city;
    private String state;
    private Contact contact;

    public Contact getContact() {
     return contact;
    }

    public void setContact(Contact contact) {
     this.contact = contact;
    }

    public String getName() {
     return name;
    }

    public void setName(String name) {
     this.name = name;
    }

    public String getAddress() {
     return address;
    }

    public void setAddress(String address) {
     this.address = address;
    }

    public String getCity() {
     return city;
    }

    public void setCity(String city) {
     this.city = city;
    }

    public String getState() {
     return state;
    }

    public void setState(String state) {
     this.state = state;
    }

}

class Contact {
    String firstName;
    String lastName;
    long phone;
    String email;

    public String getFirstName() {
     return firstName;
    }

    public void setFirstName(String firstName) {
     this.firstName = firstName;
    }

    public String getLastName() {
     return lastName;
    }

    public void setLastName(String lastName) {
     this.lastName = lastName;
    }

    public long getPhone() {
     return phone;
    }

    public void setPhone(long phone) {
     this.phone = phone;
    }

    public String getEmail() {
     return email;
    }

    public void setEmail(String email) {
     this.email = email;
    }
}

class FullOrder {
   Order myOrder;
   Address address;

   public Order getMyOrder() {
        return order;
   }

   public void setMyOrder(Order order) {
       this.order = order;
   }

   public Address getAddress() {
       return address;
   }

   public void setAddress(Address address) {
      this.address = address;
   }

}

This is structure of your json, you only need to copy it and use the Object mapper to parse the json to the pojo (FullOrder) that contains the other pojos and properties

    String json; // your json here
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.readValue(json, FullOrder.class);

Upvotes: 1

Taher
Taher

Reputation: 33

you can use the composition design pattern and have an instance of each object in a wrapper class. Or you can try to parse the json into a map and write code to instantiate and set the variables as needed.

Upvotes: 1

Jerome Anthony
Jerome Anthony

Reputation: 8021

You could use eclipse link moxy for this. It uses JAXB style annotations for field to JSON/XML mapping.

Moxy is part of eclipse link.

Wikipedia:

EclipseLink is the open source Eclipse Persistence Services Project from the Eclipse Foundation. The software provides an extensible framework that allows Java developers to interact with various data services, including databases, web services, Object XML mapping (OXM), and Enterprise Information Systems (EIS).

So in your code you would use it like;

Model A:

@XmlElement(name="completed_in")
public float getCompletedIn() {
    return completedIn;
}

Model B:

@XmlElement(name="created_at")
@XmlJavaTypeAdapter(DateAdapter.class)
public Date getCreatedAt() {
    return createdAt;
}

public void setCreatedAt(Date createdAt) {
    this.createdAt = createdAt;
}

@XmlElement(name="from_user")
public String getFromUser() {
    return fromUser;
}

Json:

{
  "completed_in":0.153,
  {
    "created_at":"Fri, 12 Aug 2011 01:14:57 +0000",
    "from_user":"stackfeed",

Upvotes: 1

chinaowl
chinaowl

Reputation: 532

I'm currently using Jackson on my project. You have the option of annotating your POJO fields with @JsonProperty or @JsonUnwrapped. You would use @JsonUnwrapped on Order, for example, and then Order would have two fields (supplier and orderName) that use @JsonProperty.

See here for more details.

Upvotes: 1

Related Questions