2

JSON Request:

{
    "notificationType" : "ISSUER_OTP1ee2asasa",
    "content" : "hi fff this is fff template content for SBI email good and mobile dfdfdfd and remaining balance is 333 and your name is hahaha.",
    "medium" : "EMAIL",
    "asa":"ddddd",
    "":""
}

POJO:

package com.innoviti.notification.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;


@Document(collection = "NotificationTemplate")
@JsonIgnoreProperties(ignoreUnknown=false)

public class NotificationTemplate {
  @JsonCreator
  public NotificationTemplate(@JsonProperty(value="notificationType",required=true)String notificationType, 
      @JsonProperty(value="content",required=true)String content, @JsonProperty(value="medium",required=true)String medium) {
    super();
    this.notificationType = notificationType;
    this.content = content;
    this.medium = medium;
  }

  @Override
  public String toString() {
    return "NotificationTemplate [id=" + id + ", templateId=" + templateId + ", notificationType="
        + notificationType + ", content=" + content + ", medium=" + medium + "]";
  }

  public String getId() {
    return id;
  }

  public void setId(String id) {
    this.id = id;
  }

  @Id
  private String id;
  private String templateId;

  public String getTemplateId() {
    return templateId;
  }

  public void setTemplateId(String templateId) {
    this.templateId = templateId;
  }

  private String notificationType;
  private String content;
  private String medium;

  public String getMedium() {
    return medium;
  }

  public void setMedium(String medium) {
    this.medium = medium;
  }

  public String getNotificationType() {
    return notificationType;
  }

  public void setNotificationType(String notificationType) {
    this.notificationType = notificationType;
  }

  public String getContent() {
    return content;
  }

  public void setContent(String content) {
    this.content = content;
  }


}

Controller where payload is posted.

 @PostMapping(value = "/config", consumes = MediaType.APPLICATION_JSON_VALUE,
      produces = MediaType.APPLICATION_JSON_VALUE)
  public ResponseEntity<NotificationTemplate> configureTemplate(
     @Valid @RequestBody NotificationTemplate notificationTemplate) {
    NotificationTemplate notificationTemplatePersisted = null;

    logger.info(
        "Printing payload of template on server side" + ">>>" + notificationTemplate.toString());
    try {
      validatePayLoad(notificationTemplate);
      notificationTemplatePersisted =
          notificationTemplateService.createNotificationTemplate(notificationTemplate);
    } catch (Exception de) {
      logger.info(String.format("Error in saving template", de.getMessage()));
      throw new RequestNotCompletedException(de.getLocalizedMessage());
    }
    return new ResponseEntity<NotificationTemplate>(notificationTemplatePersisted,
        HttpStatus.CREATED);
  }

Question:How do I validate that an uknown property has been sent as part of payload.In Existing implementation,@RequestBody maps the json without any issue.I want to throw error or validate payload if incoming json is not confirming exactly to POJO.For e.g in payload example i gave,I want to be able to throw error saying that asa is not recognized property

Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
MrWayne
  • 309
  • 1
  • 9
  • 20

2 Answers2

2

The Jackson property that controls this behaviour is FAIL_ON_UNKNOWN_PROPERTIES. This needs to be true in your case, to get the behaviour you describe.

It seems that since spring boot 1.2 this is set to false by default.

To set it to true add this line to your application.properties file:

spring.jackson.deserialization.fail-on-unknown-properties=true

And then you will get a JsonMappingException when there are extraneous properties in a JSON payload

Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
  • I thought that should be the purpose of the @JsonIgnoreProperties annotation, namely to override this setting on the POJO level. It seems that it is ignored however. – klausch Dec 19 '19 at 11:42
1
One can add this class int their project and it would throw an exception if json is mismatched to the pojo class properties.

 @Configuration
public class Config implements InitializingBean {

    @Autowired
    private RequestMappingHandlerAdapter converter;

    @Override
    public void afterPropertiesSet() throws Exception {
        configureJacksonToFailOnUnknownProperties();
    }

    private void configureJacksonToFailOnUnknownProperties() {
        MappingJackson2HttpMessageConverter httpMessageConverter = converter.getMessageConverters().stream()
                                                                            .filter(mc -> mc.getClass()
                                                                                            .equals(MappingJackson2HttpMessageConverter.class))
                                                                            .map(mc -> (MappingJackson2HttpMessageConverter) mc)
                                                                            .findFirst()
                                                                            .get();



        httpMessageConverter.getObjectMapper().enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    }
}
dhruv_0707
  • 41
  • 9
  • 1
    This is really helpful to block the request from getting processed when any unknown field(s) are sent in JSON request. Also getting a Bad Request 400 error response now, But the only additional thing I am looking for is, how to set a custom message for Bad Request 400 in this case. – Mandar Pandit Apr 02 '21 at 09:34
  • When combined the solution from these 2 links: It worked for me exactly the way I wanted. Solution Links: 1) https://stackoverflow.com/a/60643988 2) https://stackoverflow.com/a/41308274 – Mandar Pandit Apr 02 '21 at 14:05