Thursday, 21 March 2013

How to Use PropertyNamingStrategy in JACKSON

Jackson api is used extensively to convert json to Object and Object to JSON.So if you have a json string and want to convert it in a java object , create field names of bean same as the fields in json.
Jackson follows standard bean convention in mapping json fields to java object fields , but if you have a json which does not follow naming conventions [for ex fields starting with capital case] , jackson does not know how to map this fields with your java object .
You can use @JsonProperty annotation , but sometimes its hard to put this annotation on every field of every class .That's where PropertyNamingStrategy comes in to picture . You can modify this class according to your needs.
Let's take an example. We have a json like this :
{"CustName":"Abhishek Somani","Result":null,"CustNo":"1234"}
Note here , firs letter of every field is capital letter , which is not the standard bean naming convention. And we are trying to map this json to following bean :
public class JsonBean {
 /**
  * 
  */
 
 private String custNo ;
 private String custName ; 
 private String result;

 public String getResult() {
  return result;
 }
 public void setResult(String result) {
  this.result = result;
 }
 public String getCustNo() {
  return custNo;
 }
 public void setCustNo(String custNo) {
  this.custNo = custNo;
 }
 public String getCustName() {
  return custName;
 }
 public void setCustEm(String custName) {
  this.custName = custName;
 }
}
To map this json to jsonBean , we have to create our own custom naming strategy like this. Here We are converting first letter of the field name to upper case.

import org.codehaus.jackson.map.MapperConfig;
import org.codehaus.jackson.map.PropertyNamingStrategy;
import org.codehaus.jackson.map.introspect.AnnotatedField;
import org.codehaus.jackson.map.introspect.AnnotatedMethod;

public class MyNameStrategy extends PropertyNamingStrategy
 {
  @Override
  public String nameForField(MapperConfig config,
   AnnotatedField field, String defaultName) {
     return convert(defaultName);
   
  }
  @Override
  public String nameForGetterMethod(MapperConfig config,
   AnnotatedMethod method, String defaultName) {
     return convert(defaultName);
  }
  
  @Override
  public String nameForSetterMethod(MapperConfig config,
    AnnotatedMethod method, String defaultName) {
   String a = convert(defaultName); 
   return a;
  }
  
  public String convert(String defaultName )
  {
   char[] arr = defaultName.toCharArray();
   if(arr.length !=0)
   {
    if ( Character.isLowerCase(arr[0])){
     char upper = Character.toUpperCase(arr[0]);
     arr[0] = upper;
    }
   }
   return new StringBuilder().append(arr).toString();
  }
  
  
 }
This is the main class to test . We are setting our customNamingStrategy in ObjectMapper of Jackson.
import java.io.File;
import java.io.IOException;

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;


public class JsonTest {
 
 public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
  ObjectMapper mapper = new ObjectMapper();
  mapper.setPropertyNamingStrategy(new MyNameStrategy());
  File f = new File("F:/abc.json");
  JsonBean bean = (JsonBean)mapper.readValue(f, JsonBean.class);
  
  mapper.writeValue(new File("F:/abc1.json"),bean);
  
  System.out.println(bean.getCustEm());
 }
  
}
If you fail to provide a naming strategy , you will get Exception like this :
Exception in thread "main" org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "CustNo" (Class JsonBean), not marked as ignorable


Post comments and share if you like this post!!