DATAREST-531 - JSON Schema now exposes read-only fields.
Properties considered read-only are now explicitly marked as such in the JSON Schema output we render. Related tickets: DATAREST-530.
This commit is contained in:
@@ -65,7 +65,8 @@ public class JsonSchema {
|
||||
* @param properties must not be {@literal null}.
|
||||
* @param descriptors must not be {@literal null}.
|
||||
*/
|
||||
public JsonSchema(String title, String description, Collection<JsonSchemaProperty> properties, Descriptors descriptors) {
|
||||
public JsonSchema(String title, String description, Collection<JsonSchemaProperty<?>> properties,
|
||||
Descriptors descriptors) {
|
||||
|
||||
Assert.hasText(title, "Title must not be null or empty!");
|
||||
Assert.notNull(properties, "JsonSchemaProperties must not be null!");
|
||||
@@ -174,7 +175,7 @@ public class JsonSchema {
|
||||
* @param type must not be {@literal null}.
|
||||
* @param properties must not be {@literal null}.
|
||||
*/
|
||||
public Item(TypeInformation<?> type, Collection<JsonSchemaProperty> properties) {
|
||||
public Item(TypeInformation<?> type, Collection<JsonSchemaProperty<?>> properties) {
|
||||
|
||||
this.type = toJsonSchemaType(type);
|
||||
this.properties = new PropertiesContainer(properties);
|
||||
@@ -199,7 +200,7 @@ public class JsonSchema {
|
||||
@JsonInclude(Include.NON_EMPTY)
|
||||
static class PropertiesContainer {
|
||||
|
||||
public final Map<String, JsonSchemaProperty> properties;
|
||||
public final Map<String, JsonSchemaProperty<?>> properties;
|
||||
public final Collection<String> requiredProperties;
|
||||
|
||||
/**
|
||||
@@ -207,14 +208,14 @@ public class JsonSchema {
|
||||
*
|
||||
* @param properties must not be {@literal null}.
|
||||
*/
|
||||
public PropertiesContainer(Collection<JsonSchemaProperty> properties) {
|
||||
public PropertiesContainer(Collection<JsonSchemaProperty<?>> properties) {
|
||||
|
||||
Assert.notNull(properties, "JsonSchemaPropertys must not be null!");
|
||||
|
||||
this.properties = new HashMap<String, JsonSchema.JsonSchemaProperty>();
|
||||
this.properties = new HashMap<String, JsonSchema.JsonSchemaProperty<?>>();
|
||||
this.requiredProperties = new ArrayList<String>();
|
||||
|
||||
for (JsonSchemaProperty property : properties) {
|
||||
for (JsonSchemaProperty<?> property : properties) {
|
||||
this.properties.put(property.getName(), property);
|
||||
|
||||
if (property.isRequired()) {
|
||||
@@ -272,14 +273,18 @@ public class JsonSchema {
|
||||
* @since 2.3
|
||||
*/
|
||||
@JsonInclude(Include.NON_EMPTY)
|
||||
abstract static class JsonSchemaProperty {
|
||||
abstract static class JsonSchemaProperty<T extends JsonSchemaProperty<T>> {
|
||||
|
||||
private final String name;
|
||||
private final boolean required;
|
||||
|
||||
private boolean readOnly;
|
||||
|
||||
protected JsonSchemaProperty(String name, boolean required) {
|
||||
|
||||
this.name = name;
|
||||
this.required = required;
|
||||
this.readOnly = false;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@@ -290,6 +295,16 @@ public class JsonSchema {
|
||||
private boolean isRequired() {
|
||||
return required;
|
||||
}
|
||||
|
||||
public boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected T withReadOnly() {
|
||||
this.readOnly = true;
|
||||
return (T) this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,7 +313,7 @@ public class JsonSchema {
|
||||
* @author Oliver Gierke
|
||||
* @since 2.3
|
||||
*/
|
||||
static class Property extends JsonSchemaProperty {
|
||||
static class Property extends JsonSchemaProperty<Property> {
|
||||
|
||||
private static final TypeInformation<?> STRING_TYPE_INFORMATION = ClassTypeInformation.from(String.class);
|
||||
|
||||
|
||||
@@ -140,13 +140,13 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric
|
||||
final ResourceMetadata metadata = mappings.getMappingFor(persistentEntity.getType());
|
||||
|
||||
Descriptors descriptors = new Descriptors();
|
||||
List<JsonSchemaProperty> propertiesFor = getPropertiesFor(persistentEntity.getType(), metadata, descriptors);
|
||||
List<JsonSchemaProperty<?>> propertiesFor = getPropertiesFor(persistentEntity.getType(), metadata, descriptors);
|
||||
|
||||
return new JsonSchema(persistentEntity.getName(), resolveMessage(metadata.getItemResourceDescription()),
|
||||
propertiesFor, descriptors);
|
||||
}
|
||||
|
||||
private List<JsonSchemaProperty> getPropertiesFor(Class<?> type, final ResourceMetadata metadata,
|
||||
private List<JsonSchemaProperty<?>> getPropertiesFor(Class<?> type, final ResourceMetadata metadata,
|
||||
final Descriptors descriptors) {
|
||||
|
||||
final PersistentEntity<?, ?> entity = entities.getPersistentEntity(type);
|
||||
@@ -154,10 +154,10 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric
|
||||
final AssociationLinks associationLinks = new AssociationLinks(mappings);
|
||||
|
||||
if (entity == null) {
|
||||
return Collections.<JsonSchemaProperty> emptyList();
|
||||
return Collections.<JsonSchemaProperty<?>> emptyList();
|
||||
}
|
||||
|
||||
final List<JsonSchemaProperty> properties = new ArrayList<JsonSchema.JsonSchemaProperty>();
|
||||
final List<JsonSchemaProperty<?>> properties = new ArrayList<JsonSchema.JsonSchemaProperty<?>>();
|
||||
|
||||
for (BeanPropertyDefinition definition : jackson) {
|
||||
|
||||
@@ -171,6 +171,10 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric
|
||||
: getDescriptionFor(persistentProperty, metadata);
|
||||
Property property = getSchemaProperty(definition, propertyType, description);
|
||||
|
||||
if (persistentProperty != null && !persistentProperty.isWritable()) {
|
||||
property = property.withReadOnly();
|
||||
}
|
||||
|
||||
if (format != null) {
|
||||
|
||||
// Types with explicitly registered format -> value object with format
|
||||
@@ -222,7 +226,8 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric
|
||||
return properties;
|
||||
}
|
||||
|
||||
private Collection<JsonSchemaProperty> getNestedPropertiesFor(PersistentProperty<?> property, Descriptors descriptors) {
|
||||
private Collection<JsonSchemaProperty<?>> getNestedPropertiesFor(PersistentProperty<?> property,
|
||||
Descriptors descriptors) {
|
||||
|
||||
if (!property.isEntity()) {
|
||||
return Collections.emptyList();
|
||||
|
||||
@@ -124,6 +124,9 @@ public class PersistentEntityToJsonSchemaConverterUnitTests {
|
||||
constraints.add(new Constraint("$.properties.shippingAddresses.items['$ref']", is("#/descriptors/address"),
|
||||
"References descriptor of complex element type."));
|
||||
|
||||
// DATAREST-531
|
||||
constraints.add(new Constraint("$.properties.email.readOnly", is(true), "Email is read-only property"));
|
||||
|
||||
assertConstraints(User.class, constraints);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,7 @@ import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.annotation.ReadOnlyProperty;
|
||||
import org.springframework.data.mongodb.core.mapping.DBRef;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
@@ -41,7 +42,7 @@ public class User {
|
||||
public Set<Address> shippingAddresses;
|
||||
public List<String> nicknames;
|
||||
public Gender gender;
|
||||
public EmailAddress email;
|
||||
public @ReadOnlyProperty EmailAddress email;
|
||||
public LocalDateTime java8DateTime;
|
||||
public org.joda.time.LocalDateTime jodaDateTime;
|
||||
public TypeWithPattern pattern;
|
||||
@@ -57,8 +58,8 @@ public class User {
|
||||
public EmailAddress(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
@Override
|
||||
|
||||
@Override
|
||||
@JsonValue
|
||||
public String toString() {
|
||||
return value;
|
||||
|
||||
Reference in New Issue
Block a user