PropertyEditor not being called on AJAX request (JSON)

I have a problem with Ajax request on form submission. The form contains this JSON string data:

{"articleContent":"<p>aaa</p>","title":"Po vyplnění titulku aktuality budete","header":"aa","enabled":false,"timestamp":"1358610697521","publishedSince":"03.01.2013 00:00","publishedUntil":"","id":"10"}

      

When json contains "01/03/2013 00:00" , the server response is 400 Bad Request

The problem is that the custom DateTimePropertyEditor (which is registered with @InitBinder) is not called, and the DateTime format in String is not fleshed out. Do you have any ideas How to solve this problem?

The managed controller that processes the request

@RequestMapping( value = "/admin/article/edit/{articleId}", method = RequestMethod.POST, headers = {"content-type=application/json"})
public @ResponseBody JsonResponse  processAjaxUpdate(@RequestBody Article article, @PathVariable Long articleId){
    JsonResponse response = new JsonResponse();
    Article persistedArticle = articleService.getArticleById(articleId);
    if(persistedArticle == null){
        return response;
    }
    List<String> errors = articleValidator.validate(article, persistedArticle);

    if(errors.size() == 0){
        updateArticle(article, persistedArticle);
        response.setStatus(JsonStatus.SUCCESS);
        response.setResult(persistedArticle.getChanged().getMillis());
    }else{
        response.setResult(errors);
    }

    return response;
}

      

InitBinder

 @InitBinder
        public void initBinder(WebDataBinder binder) {
            binder.registerCustomEditor(DateTime.class, this.dateTimeEditor);
        }

      

+3


source to share


3 answers


I solved this problem with @JsonDeserialize

@JsonDeserialize(using=DateTimeDeserializer.class)
public DateTime getPublishedUntil() {
    return publishedUntil;
}

      



I need to implement a custom deserializer.

    public class DateTimeDeserializer extends StdDeserializer<DateTime> {

    private DateTimeFormatter formatter = DateTimeFormat.forPattern(Constants.DATE_TIME_FORMAT);

    public DateTimeDeserializer(){
        super(DateTime.class);
    }

    @Override
    public DateTime deserialize(JsonParser json, DeserializationContext context) throws IOException, JsonProcessingException {
            try {
                if(StringUtils.isBlank(json.getText())){
                    return null;
                }
                return formatter.parseDateTime(json.getText());
            } catch (ParseException e) {
                return null;
            }
    }
}

      

+5


source


This is not handled by the Property Editor which acts on form fields and not on json bodies. To handle non-standard date format in json, you will have to tweak the underlying ObjectMapper . Assuming you are using jackson 2.0+, this is what you can do:

and. Mark the publishSince field with an annotation that tells the Object mapper the date format - based on the instructions here :

public class Article{
    ...
    @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="MM.dd.yyyy HH:mm")
    private Date publishedSince;
}

      

b. Or the second option is to change the ObjectMapper itself, this might be global, but might not work for you:



public class CustomObjectMapper extends ObjectMapper {
    public CustomObjectMapper(){
        super.setDateFormat(new SimpleDateFormat("MM.dd.yyyy hh:mm"));
    }   
}

      

and set it up with Spring MVC:

<mvc:annotation-driven> 
   <mvc:message-converters register-defaults="true">
       <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
           <property name="objectMapper">
               <bean class="..CustomObjectMapper"/>
           </property>
       </bean>
   </mvc:message-converters>
</mvc:annotation-driven>

      

+2


source


As of Spring MVC 4.2.1.RELEASE, you need to use the new Jackson2 dependencies as shown below for the Deserializer to work.

Don't use this

<dependency>  
            <groupId>org.codehaus.jackson</groupId>  
            <artifactId>jackson-mapper-asl</artifactId>  
            <version>1.9.12</version>  
        </dependency>  

      

Use this instead.

<dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.2.2</version>
        </dependency>  

      

Also use com.fasterxml.jackson.databind.JsonDeserializer and com.fasterxml.jackson.databind.annotation.JsonDeserialize for deserialization, not classes from org.codehaus.jackson

0


source







All Articles