我们的REST API收到一些JSON对象输入,其中某些字段必须不为null。那些可以是String / Integer,也可以是其他类实例作为参考。
我们正试图找到一种方法来强制将这些字段设为非空,而不是在api中进行空检查的正确方法。 电流:
if (myObject.getSomeOtherObject() == null) throw new SomeException();
我们想拥有的是:
class MyObject{ @Required OtherObject someOtherObject; ... }
我们尝试了3件事:
升级到jackson 2.0.6并使用注释 com.fasterxml.jackson.annotation.JsonProperty 但是,这看起来不起作用。 找到那些参考: http://jira.codehaus.org/browse/JACKSON-767
扩展JsonDeserializer以检查null,但问题是它甚至没有在空输入上执行。
public class NotNullDeserializer<T> extends JsonDeserializer<T> { @Override public T deserialize(JsonParser jsonparser, DeserializationContext deserializationcontext) throws IOException, JsonProcessingException { ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass(); Class type = (Class) superClass.getActualTypeArguments()[0]; T t = jsonparser.readValueAs(type); if (t == null){ String classNameField = type.getName(); String field = jsonparser.getCurrentName(); throw new WrongInputException("The field '"+field+"' of type '"+classNameField+"' should not be null."); } return t; } } public class NotNullAddressDeserializer extends NotNullDeserializer<Address> { } @JsonDeserialize(using=NotNullAddressDeserializer.class) Address to;
private class Filter implements ResourceFilter, ContainerRequestFilter { private final ArrayList requiredParameters; protected Filter() { requiredParameters = null; } protected Filter(ArrayList requiredParameters) { this.requiredParameters = requiredParameters; } @Override public ContainerRequestFilter getRequestFilter() { return this; } @Override public ContainerResponseFilter getResponseFilter() { return null; } @Override public ContainerRequest filter(ContainerRequest request) { if (requiredParameters != null && requiredParameters.size() > 0) { MultivaluedMap params = request.getQueryParameters(); params.putAll(request.getFormParameters()); StringBuffer missingParams = new StringBuffer(); for (String reqParam : requiredParameters) { List paramValues = params.get(reqParam); if (paramValues == null || paramValues != null && paramValues.size() == 0) missingParams.append(reqParam + ","); } if (missingParams.length() > 0) throw new WrongInputException("Required parameters are missing: " + missingParams); } return request; } }
任何帮助和见解表示赞赏。
答案 0 :(得分:23)
JAX-RS很好地将反序列化与验证区分开来,即杰克逊有按设计没有机制来强制值为non-null
等。相反,你可以使用BeanValidation来实现:
javax.validation:validation-api
范围内向provided
添加依赖项。javax.validation.constraints.NotNull
注释添加到您的字段中。有关详细信息,请转到here。
答案 1 :(得分:2)
您可以使用JSON-SCHEMA,因为您可以使用它来表达JSON字段的许多约束:http://json-schema.org/
然后,您可以使用@NotNull JSR 303注释从模式生成java类,并在对象上使用bean验证。它本身与杰克逊合作,所以你不应该有任何问题。
例如,您可以使用maven插件执行此操作:http://wiki.jsonschema2pojo.googlecode.com/git/site/0.3.7/generate-mojo.html
答案 2 :(得分:1)
@Required
是注入bean的Spring框架注释,所以我要说不要将它用于此目的。
你可以改用这个:
http://robaustin.wikidot.com/annotations-and-notnull
@NotNull
String myString;
对于运行时检查,请尝试http://code.google.com/p/notnullcheckweaver/
答案 3 :(得分:0)
您可以结合使用Jackson JSON库和not null
以及Hibernate验证程序包来强制执行javax.validation
验证。
如果您正在使用Maven,则可以使用以下依赖项:
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.6</version>
</dependency>
</dependencies>
然后,您的代码将必须将一些JSON转换为带注释的对象,并且您将需要使用javax.validation.Validator
来验证对象。以下是一些示例代码,演示了如何完成此操作(请参见相关的validate
方法):
public class ShareLocationService {
private ObjectMapper mapper = new ObjectMapper();
private ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
// Materialize the Java object which contains the validation annotations
public ShareLocation readFrom(String json) throws IOException {
return mapper.readerFor(ShareLocation.class).readValue(json);
}
// validate and collect the set of validations
public Set<String> validate(String json) throws IOException {
ShareLocation shareMyLocation = readFrom(json);
Validator validator = factory.getValidator();
Set<ConstraintViolation<ShareLocation>> violations = validator.validate(shareMyLocation);
return violations.stream().map(Object::toString).collect(Collectors.toSet());
}
}
这是使用验证注释的示例类:
public class ShareLocation {
@JsonProperty("Source")
@NotNull
private String source;
@JsonProperty("CompanyCode")
private String companyCode;
@JsonProperty("FirstName")
private String firstName;
@JsonProperty("LastName")
private String lastName;
@JsonProperty("Email")
private String email;
@JsonProperty("MobileNumber")
private String mobileNumber;
@JsonProperty("Latitude")
@NotNull
private Double latitude;
@JsonProperty("Longitude")
@NotNull
private Double longitude;
@JsonProperty("LocationDateTime")
@NotNull
private String locationDateTime;