Confirm entry before Jackson in Spring Boot

I have built a REST endpoint using Spring Boot. JSON

sent to the endpoint. Jackson transforms JSON

by giving me an object.

JSON

looks like that:

{
    "parameterDateUnadjusted": "2017-01-01",
    "parameterDateAdjusted": "2017-01-02"
}

      

Jackson converts JSON

to an object based on this class:

public class ParameterDate {

    @NotNull(message = "Parameter Date Unadjusted can not be blank or null")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date parameterDateUnadjusted;
    @NotNull(message = "Parameter Date Adjusted can not be blank or null")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date parameterDateAdjusted;
    private Date parameterDateAdded;
    private Date parameterDateChanged;
}

      

This all works great. The problem I am facing is that I would like to validate the data before Jackson transforms the data. For example, if I send

{
    "parameterDateUnadjusted": "2017-01-01",
    "parameterDateAdjusted": "2017-01-40"
}

      

Where is parameterDateAdjusted

not a valid date (it does not include a 40-day month). Jackson converts this value to 2017-02-09

. One way to get around this is to have a string-only class name it ParameterDateInput

. Validate each Hibernate Validator object ParameterDateInput

and then copy the object ParameterDateInput

into parameterDate

where each field is of the correct type (dates are of type Date

, not type String

). This doesn't sound like a very elegant solution to me. Is there any other way to solve this problem? How is data typically validated in Spring Boot when sent how JSON

? I like to send a message to the user / client what is wrong with the data being sent.

+3


source to share


2 answers


There is a way to check dates. setLenient()

method

public static boolean isValidDate(String inDate, String format) {
    SimpleDateFormat dateFormat = new SimpleDateFormat(format);
    dateFormat.setLenient(false);
    try {
      dateFormat.parse(inDate.trim());
    } catch (ParseException pe) {
      return false;
    }
    return true;
 }

      

Just define your own annotation to check the value



@Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = MyDateFormatCheckValidator.class)
@Documented
public @interface MyDateFormatCheck {
    String pattern();
...

      

and the validator class

public class MyDateFormatCheckValidator implements ConstraintValidator<MyDateFormatCheck, String> {

    private MyDateFormatCheck check; 
    @Override
    public void initialize(MyDateFormatCheck constraintAnnotation) {
        this.check= constraintAnnotation;
    }

    @Override
    public boolean isValid(String object, ConstraintValidatorContext constraintContext) {
        if ( object == null ) {
            return true;
        }

        return isValidDate(object, check.pattern());
    }
}

      

0


source


How about a custom JSON deserializer where you can write the logic you want:



@RestController
public class JacksonCustomDesRestEndpoint {

    @RequestMapping(value = "/yourEndPoint", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public Object createRole(@RequestBody ParameterDate paramDate) {
        return paramDate;
    }
}

@JsonDeserialize(using = RoleDeserializer.class)
public class ParameterDate {
    // ......
}

public class RoleDeserializer extends JsonDeserializer<ParameterDate> {
    @Override
    public ParameterDate deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        ObjectCodec oc = jsonParser.getCodec();
        JsonNode node = oc.readTree(jsonParser);
        String parameterDateUnadjusted = node.get("parameterDateUnadjusted").getTextValue();
        //Do what you want with the date and set it to object from type ParameterDate and return the object at the end. 
        //Don't forget to fill all the properties to this object because you do not want to lose data that came from the request.
        return something;
    }
}

      

0


source







All Articles