wsimport generated getter not working in ObjectMapper

357 views Asked by At

Below is the class generated by wsimport - (note getter name getOProposalData()) -

public class UpdateProposalRequest {
    protected ObjProposalData oProposalData;

    public ObjProposalData getOProposalData() {
        return oProposalData;
    }
    public void setOProposalData(ObjProposalData value) {
        this.oProposalData = value;
    }
}

I am trying to convert convert a string to the object of above class using ObjectMapper from com.fasterxml.jackson.core (jackson-databind) -

private ObjectMapper mapper = new ObjectMapper();
UpdateProposalRequest requestObject = mapper.readValue(requestStr, UpdateProposalRequest.class);

requestStr is having the below JSON -

{
    "oProposalData": {
    .
    .
    .
    }
}

When i run the application, it throws the below exception - (Note - known property name - oproposalData) -

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "oProposalData" (class co.xxx.service.updateproposal.UpdateProposalRequest), not marked as ignorable (one known property: "oproposalData"])

After a bit of head scratching I figured that the problem is with the getter name generated from wsimport. If I change it to getoProposalData(), then the above exception is not thrown.

Below are the 2 workarounds I could think of for the issue -

  1. For every getter method, add the below annotation for the ObjectMapper to pick the correct field name - @JsonProperty("oProposalData")

  2. After generating the class file with wsimport, use an IDE like eclipse to auto generate the getters and setter. (Eclipse will generate the getter with the proper format which matches the ObjectMapper format).

The problem with these methods is that I have got hundreds of such class files having multiple fields. So manually adding the annotation or generating the getters and setters will take a lot of time. Also any small change to the WSDL file will result in regenerating the class files and again changing the getter names manually.

Is there a way to control the getter/setter name format while generating the class files?

Or is there a way to provide the getter format to the ObjectMapper while calling the readValue/writeValue?

Update -

I found that by extending PropertyNamingStrategy, we will be able to provide our own conversion strategy. But I am not able to get the conversion right for the above case. Link -- Link

Can anyone please provide the exact conversion strategy needed in the above case?

1

There are 1 answers

0
Nithin Kumar Biliya On BEST ANSWER

I got it working by using PropertyNamingStrategy as below --

public class MyNameStrategy extends PropertyNamingStrategy {
    @Override
    public String nameForField(MapperConfig config, AnnotatedField field, String defaultName) {
        return convertFieldName(field.getName());
    }

    @Override
    public String nameForGetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) {
        return convertMethodName(method.getName(),defaultName);
    }

    @Override
    public String nameForSetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) {
        return convertMethodName(method.getName(),defaultName); 
    }

    public String convertMethodName(String methodName,String defaultName) {
        if(methodName.compareTo("isEmpty")==0 || methodName.compareTo("isNaN")==0 || methodName.compareTo("isInfinite")==0) {
            return defaultName;
        }
        return convertFieldName(methodName.substring(3));
    }

    public String convertFieldName(String fieldName) {
        char[] arr=fieldName.toCharArray();
        if(arr.length!=0) {
            if(Character.isUpperCase(arr[0])){
                char lower = Character.toLowerCase(arr[0]);
                arr[0] = lower;
            }
        }
        return new StringBuilder().append(arr).toString();
    }
}

Using the above class object as below -

ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new MyNameStrategy());
UpdateProposalRequest requestObject=mapper.readValue(request, UpdateProposalRequest.class);