当前位置: 首页 > 面试题库 >

@在没有控制器的情况下使用jackson创建对象时有效

潘安平
2023-03-14
问题内容

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

@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中的变量?


问题答案:

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

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

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()
}

For valid JSON payload:

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

prints:

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

For invalid JSON payload:

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

prints:

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的ObjectMapper创建了一个对象。有没有一种方法可以在ObjectMapper中注册此验证,还是应该只检查setter中的变量? 问题答案: 反序列化后,您可以扩展和验证对象。要注册此bean使用。 具有验证的简单bean反序列化器: 我们可以如下使用它:

  • 我试着去看其他的代码例子,但是它们和我的代码比较相似,但是我的应用程序仍然会因为同样的错误而崩溃。 这是我使用firebase文档的指导方针编写的代码: 上面的代码正在将otp发送到给定的号码,但是它崩溃了,并且cat-log显示了上面提到的错误。

  • 我看到的所有解决方案都需要使用。但是,我想在Eclipse之外的单个文件上使用CDT解析器。那有什么办法吗?

  • 问题内容: 我正在寻找一种通过字符串值访问属性的好的解决方案,但是如果该属性不存在,则应该创建它。如果根结构已经定义了结构的某些部分,则属性不应被覆盖,而应合并。 例如,如果您有一个空对象,并且想要设置一个深层结构而不使用eval。例如 我写了一个切实可行的解决方案,但是我猜这是很糟糕的代码: 也可以作为jsfiddle使用:https ://jsfiddle.net/gvaLzqqf/4/ 但是

  • 所以,我想做的是: 创建水果的对象作为键和它们出现的次数。结束对象如下所示: 所以对于“苹果”来说: 我回顾了一堆帖子和链接,这些帖子和链接让我陷入了一个兔子洞。即便如此,他们中没有一个明确地解决了我所能说出的问题。 这段代码中Number对象保存属性并增加数字时发生了什么? 如何增加JavaScript对象中的值? 如何在JavaScript中使用for…语法获得循环计数器/索引? 遍历对象数组

  • 问题内容: 我有一个没有情节提要的应用程序,所有UI创建都是通过代码完成的,我得到了一个我可以使其在iPhone上使用的应用程序,因为该应用程序最初仅是为iPad设计的,因此当您在列表中选择一行时,大师认为,它在iPhone上什么也不做,但在iPad上工作正常。 所以我的问题是我可以创建并执行允许在方法上显示“详细视图”的segue 吗? 到目前为止,这是我所做的: 但是当运行并选择一行时,应用程