Search code examples
javaspring-mvcjacksondeserializationspring-mvc-initbinders

How to write initbinder for json deserialization?


I have the following POJO:

class MyClass{
    ...
    HttpStatus httpStatus = HttpStatus.OK //from org.springframework.http
    @JsonIgnore
    public HttpStatus getHttpStatus() {
        return httpStatus;
     }

    @JsonProperty(value = "HttpStatus")
    public void setHttpStatus(HttpStatus httpStatus) {
        this.httpStatus = httpStatus;
    }
    ....
}

When I accept(construct) object from form to correct convert String to HttpStatus I have wrote InitBinder:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(HttpStatus.class, new PropertyEditorSupport() {
        public void setAsText(String code) {
            if (StringUtils.isNotBlank(code)) {
                setValue(HttpStatus.valueOf(Integer.parseInt(code)));
            }
        }
    });

For form it works cool.

I also have controller method which accepts json:

@RequestMapping(value = "sendData.json", method = RequestMethod.POST, consumes = "application/json;charset=UTF-8",
            headers = "content-type=application/x-www-form-urlencoded")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void putJsonData(@RequestBody MyClass myClass) {
        ....
    }

I pass httpStatus like this:

...
"HttpStatus":500
...

but it converts incorrect and I see following error message:

Bad Request","exception":"org.springframework.http.converter.HttpMessageNotReadableException","message":"Could not read JSON: Can not construct instance of org.springframework.http.HttpStatus from number value (500): index value outside legal index range [0..65]\n

As I understand it converts incorrect.

How can I customize this process ?


Solution

  • Problem was resolved like this:

    class MyClass{
        ...
        HttpStatus httpStatus = HttpStatus.OK //from org.springframework.http
        @JsonIgnore
        public HttpStatus getHttpStatus() {
            return httpStatus;
         }
    
        @JsonProperty(value = "HttpStatus")
        @JsonDeserialize(using = HttpStatusDeserializer.class)
        public void setHttpStatus(HttpStatus httpStatus) {
            this.httpStatus = httpStatus;
        }
        ....
    }
    

    and deserializer:

    public class HttpStatusDeserializer extends JsonDeserializer<HttpStatus> {    
        @Override
        public HttpStatus deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
            ObjectCodec oc = jsonParser.getCodec();
            JsonNode node = oc.readTree(jsonParser);
            return HttpStatus.valueOf(Integer.parseInt(node.asText()));
        }
    }