@Valid 在没有控制器的情况下使用 jackson 创建对象时 [英] @Valid when creating objects with jackson without controller

查看:34
本文介绍了@Valid 在没有控制器的情况下使用 jackson 创建对象时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模型,当从前端发送请求时,我在控制器中使用 @Valid 进行验证:

I have a model that I validate with @Valid in my Controllers when requests are send from the front-end:

@NotNull
@Size(min=1, message="Name should be at least 1 character.")
private String name;

@NotNull
@Pattern(regexp = "^https://github.com/.+/.+$", message = "Link to github should match https://github.com/USER/REPOSITORY")
private String github;

但现在我也在用 Jackson 的 ObjectMapper 创建一个没有控制器的对象.有没有办法在 ObjectMapper 中注册这个验证,还是我应该只检查 setter 中的变量?

but now I am also creating a object with Jackson's ObjectMapper without the controller. Is there a way to register this validation in the ObjectMapper or should I just check the variables in the setters?

推荐答案

您可以扩展 BeanDeserializer 并在反序列化后验证对象.要注册此 bean,请使用 SimpleModule.

You can extend BeanDeserializer and validate object after deserialisation. To register this bean use SimpleModule.

带验证的简单 bean 反序列化器:

Simple bean deserialiser with validation:

class BeanValidationDeserializer extends BeanDeserializer {

    private final static ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    private final Validator validator = factory.getValidator();

    public BeanValidationDeserializer(BeanDeserializerBase src) {
        super(src);
    }

    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        Object instance = super.deserialize(p, ctxt);
        validate(instance);

        return instance;
    }

    private void validate(Object instance) {
        Set<ConstraintViolation<Object>> violations = validator.validate(instance);
        if (violations.size() > 0) {
            StringBuilder msg = new StringBuilder();
            msg.append("JSON object is not valid. Reasons (").append(violations.size()).append("): ");
            for (ConstraintViolation<Object> violation : violations) {
                msg.append(violation.getMessage()).append(", ");
            }
            throw new ConstraintViolationException(msg.toString(), violations);
        }
    }
}

我们可以如下使用:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.BeanDeserializer;
import com.fasterxml.jackson.databind.deser.BeanDeserializerBase;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.module.SimpleModule;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.io.File;
import java.io.IOException;
import java.util.Set;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        SimpleModule validationModule = new SimpleModule();
        validationModule.setDeserializerModifier(new BeanDeserializerModifier() {
            @Override
            public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
                if (deserializer instanceof BeanDeserializer) {
                    return new BeanValidationDeserializer((BeanDeserializer) deserializer);
                }

                return deserializer;
            }
        });

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(validationModule);

        System.out.println(mapper.readValue(jsonFile, Pojo.class));
    }
}

class Pojo {

    @NotNull
    @Size(min = 1, message = "Name should be at least 1 character.")
    private String name;

    @NotNull
    @Pattern(regexp = "^https://github.com/.+/.+$", message = "Link to github should match https://github.com/USER/REPOSITORY")
    private String github;

    // getters, setters, toString()
}

对于有效的 JSON 有效负载:

For valid JSON payload:

{
  "name": "Jackson",
  "github": "https://github.com/FasterXML/jackson-databind"
}

印刷品:

Pojo{name='Jackson', github='https://github.com/FasterXML/jackson-databind'}

对于无效的 JSON 负载:

{
  "name": "",
  "github": "https://git-hub.com/FasterXML/jackson-databind"
}

印刷品:

Exception in thread "main" javax.validation.ConstraintViolationException: JSON object is not valid. Reasons (2): Name should be at least 1 character., Link to github should match https://github.com/USER/REPOSITORY, 
    at BeanValidationDeserializer.validate(JsonApp.java:110)
    at BeanValidationDeserializer.deserialize(JsonApp.java:97)

另见:

这篇关于@Valid 在没有控制器的情况下使用 jackson 创建对象时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆