Принудительное поле not-null в объекте JSON
наш REST API получает некоторые входные данные объектов JSON, где некоторые поля должны быть не нулевыми. Это может быть либо строка / целое число, либо даже какой-либо другой экземпляр класса в качестве ссылки.
мы пытаемся найти способ обеспечить, чтобы это поле не было нулевым, а не corrent-способом для нулевой проверки в api. Ток:
if (myObject.getSomeOtherObject() == null) throw new SomeException();
то, что мы хотим иметь, это что-то вроде:
class MyObject{ @Required OtherObject someOtherObject; ... }
мы попробовали 3 вещи:
обновление до jackson 2.0.6 и использование аннотации com.fasterxml.Джексон.аннотация.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;
- написание собственной аннотации @Required и попытка проверить с помощью ResourceFilter, но, похоже, я не могу получить фактический объект из ContainerRequest, и даже если бы мы могли, не знаете, как выполнить глубокую проверку нулевой ссылки в объекте.otherObject.someObject.fieldNotNullable
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; } }
Любая помощь и понимание ценятся.
4 ответов
JAX-RS довольно хорошо отделяет десериализацию от проверки, т. е. У Джексона есть конструкция нет механизма для принудительного значения non-null
, etc. Вместо этого вы можете использовать BeanValidation для этого:
- добавить зависимость к
javax.validation:validation-api
наprovided
объем. - добавить
javax.validation.constraints.NotNull
аннотация к вашему полю.
для получения более подробной информации, go здесь.
вы можете использовать JSON-SCHEMA как вы можете выразить много ограничений на полях JSON с ним:http://json-schema.org/
затем вы можете генерировать из схемы свои классы java с аннотациями @NotNull JSR 303 и использовать проверку bean для вашего объекта. Он работает с Джексоном изначально, поэтому у вас не должно быть никаких проблем.
например, вы можете использовать плагин maven для этого: http://wiki.jsonschema2pojo.googlecode.com/git/site/0.3.7/generate-mojo.html
@Required
является аннотацией Spring framework для инъекционных бобов, поэтому я бы сказал, что не используйте его для этой цели.
Вы можете использовать вместо этого:
http://robaustin.wikidot.com/annotations-and-notnull
@NotNull
String myString;
для проверки выполнения попробуйте http://code.google.com/p/notnullcheckweaver/
вы можете применять not null
проверка с использованием комбинации библиотеки Jackson JSON и javax.validation
вместе с пакетом Hibernate validator.
если вы используете 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;