Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change property names while deserialzing class to JSON in Spring MVC

I'm trying to consume a rest API call using Spring as below:

HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Creds);

HttpEntity<String> request = new HttpEntity<String>(headers);
RestTemplate restTemplate = new RestTemplate();

Item item = restTemplate.exchange(url, HttpMethod.GET, request, Item.class).getBody();

The response I get from the API is in following form:

{    
"item":[{
    "itemname": "abc",
    "qty":...
}]
}

The Item class has following fields:

Class Item{
    @JsonProperty("itemname")
    String name;
    @JsonProperty("qty")
    int quantity;

    // Getter / setter methods
}

I've added JsonProperty annotations to the fields as their names are different from the json I get from the API. With this, I'm able to deserialize the api response successfully.

However, when I try to serialize the Item class again as a json, the field names are "itemname" and "qty". Is there any way to keep these as "name" and "quantity", and yet be able to map to the API response?

Thanks in advance.

like image 676
drunkenfist Avatar asked Feb 26 '15 05:02

drunkenfist


1 Answers

  1. If you just want to serialize in different form, you can do it like this:

    public static class Item {
    
      private String name;
      private int quantity;
    
      @JsonProperty("name")
      public String getName() {
        return name;
      }
    
      @JsonProperty("itemname")
      public void setName(String name) {
        this.name = name;
      }
    
      @JsonProperty("quantity")
      public int getQuantity() {
        return quantity;
      }
    
      @JsonProperty("qty")
      public void setQuantity(int quantity) {
        this.quantity = quantity;
     }
    

    }

    This would read "{"itemname": "abc", "qty":10 }" and write "{"name": "abc", "quantity":10 }".

    But there is a big drawback - you wont be able to read "{"name": "abc", "quantity":10 }", with this ObjectMapper (This is worse possible solution).

  2. You can use 2 ObjectMappers and instead of class Annotations use Mixins, to configure specific deserialization

    This is how your Mixin would look like:

    abstract public static class ItemMixin {
        ItemMixin(@JsonProperty("itemname") String itemname, @JsonProperty("qty") int qty) { }
        // note: could alternatively annotate fields "w" and "h" as well -- if so, would need to @JsonIgnore getters
        @JsonProperty("itemname") abstract String getName(); // rename property
        @JsonProperty("qty") abstract int getQuantity(); // rename property
    }
    

    Here is how to add Mixin in ObjectMapper.

    objectMapper.addMixIn(Item.class, ItemMixinA.class);
    

    So if you Deserialize with Mixin ObjectMapper, and serialize with standard ObjectMapper there will be no problem.

  3. You can write custom JsonDeserialization for your class.

    It's easy to do for class with few fields, but complexity would grow proportionally as number of fields grows.

like image 77
mavarazy Avatar answered Oct 20 '22 02:10

mavarazy