#1151 - Make sure we explicitly expose all media type model properties.
Jackson can be configured to not auto-detect properties on objects to be rendered, requiring them to be explicitly annotated with @JsonProperty to be exposed. In such a configuration setup, some of our model types do not work properly as so far we have expected public properties to be included automatically. This commit changes that to explicitly include @JsonProperty on all of the getter methods exposed.
This commit is contained in:
@@ -37,6 +37,7 @@ import org.springframework.util.StringUtils;
|
|||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value object for links.
|
* Value object for links.
|
||||||
@@ -46,9 +47,9 @@ import com.fasterxml.jackson.annotation.JsonInclude;
|
|||||||
* @author Jens Schauder
|
* @author Jens Schauder
|
||||||
*/
|
*/
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
@JsonIgnoreProperties(value = "templated", ignoreUnknown = true)
|
@JsonIgnoreProperties(value = { "templated", "template" }, ignoreUnknown = true)
|
||||||
@AllArgsConstructor(access = AccessLevel.PACKAGE)
|
@AllArgsConstructor(access = AccessLevel.PACKAGE)
|
||||||
@Getter
|
@Getter(onMethod = @__(@JsonProperty))
|
||||||
@EqualsAndHashCode(
|
@EqualsAndHashCode(
|
||||||
of = { "rel", "href", "hreflang", "media", "title", "type", "deprecation", "profile", "name", "affordances" })
|
of = { "rel", "href", "hreflang", "media", "title", "type", "deprecation", "profile", "name", "affordances" })
|
||||||
public class Link implements Serializable {
|
public class Link implements Serializable {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
package org.springframework.hateoas.mediatype.collectionjson;
|
package org.springframework.hateoas.mediatype.collectionjson;
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.experimental.Wither;
|
import lombok.experimental.Wither;
|
||||||
|
|
||||||
@@ -39,6 +40,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
* @author Greg Turnquist
|
* @author Greg Turnquist
|
||||||
*/
|
*/
|
||||||
@Value
|
@Value
|
||||||
|
@Getter(onMethod = @__(@JsonProperty))
|
||||||
@Wither(AccessLevel.PACKAGE)
|
@Wither(AccessLevel.PACKAGE)
|
||||||
class CollectionJson<T> {
|
class CollectionJson<T> {
|
||||||
|
|
||||||
|
|||||||
@@ -15,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.hateoas.mediatype.collectionjson;
|
package org.springframework.hateoas.mediatype.collectionjson;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.experimental.Wither;
|
import lombok.experimental.Wither;
|
||||||
|
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
@@ -30,17 +30,13 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
* @author Greg Turnquist
|
* @author Greg Turnquist
|
||||||
*/
|
*/
|
||||||
@Value
|
@Value
|
||||||
|
@Getter(onMethod = @__(@JsonProperty))
|
||||||
|
@JsonInclude(Include.NON_NULL)
|
||||||
@Wither
|
@Wither
|
||||||
@JsonIgnoreProperties()
|
|
||||||
class CollectionJsonData {
|
class CollectionJsonData {
|
||||||
|
|
||||||
@JsonInclude(Include.NON_NULL) //
|
|
||||||
private @Nullable String name;
|
private @Nullable String name;
|
||||||
|
|
||||||
@JsonInclude(Include.NON_NULL) //
|
|
||||||
private @Nullable Object value;
|
private @Nullable Object value;
|
||||||
|
|
||||||
@JsonInclude(Include.NON_NULL) //
|
|
||||||
private @Nullable String prompt;
|
private @Nullable String prompt;
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
package org.springframework.hateoas.mediatype.collectionjson;
|
package org.springframework.hateoas.mediatype.collectionjson;
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.experimental.Wither;
|
import lombok.experimental.Wither;
|
||||||
@@ -33,6 +34,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
* @author Greg Turnquist
|
* @author Greg Turnquist
|
||||||
*/
|
*/
|
||||||
@Value
|
@Value
|
||||||
|
@Getter(onMethod = @__(@JsonProperty))
|
||||||
@Wither(AccessLevel.PACKAGE)
|
@Wither(AccessLevel.PACKAGE)
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
||||||
class CollectionJsonDocument<T> {
|
class CollectionJsonDocument<T> {
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import com.fasterxml.jackson.databind.JavaType;
|
|||||||
* @author Greg Turnquist
|
* @author Greg Turnquist
|
||||||
*/
|
*/
|
||||||
@Value
|
@Value
|
||||||
|
@Getter(onMethod = @__(@JsonProperty))
|
||||||
@Wither(AccessLevel.PACKAGE)
|
@Wither(AccessLevel.PACKAGE)
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
||||||
class CollectionJsonItem<T> {
|
class CollectionJsonItem<T> {
|
||||||
@@ -79,6 +80,7 @@ class CollectionJsonItem<T> {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@JsonProperty
|
||||||
public List<CollectionJsonData> getData() {
|
public List<CollectionJsonData> getData() {
|
||||||
|
|
||||||
if (!this.data.isEmpty()) {
|
if (!this.data.isEmpty()) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package org.springframework.hateoas.mediatype.hal.forms;
|
|||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
@@ -29,6 +30,7 @@ import org.springframework.hateoas.AffordanceModel.PropertyMetadataConfigured;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe a parameter for the associated state transition in a HAL-FORMS document. A {@link HalFormsTemplate} may
|
* Describe a parameter for the associated state transition in a HAL-FORMS document. A {@link HalFormsTemplate} may
|
||||||
@@ -39,6 +41,7 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
|||||||
@JsonInclude(Include.NON_DEFAULT)
|
@JsonInclude(Include.NON_DEFAULT)
|
||||||
@Value
|
@Value
|
||||||
@Wither
|
@Wither
|
||||||
|
@Getter(onMethod = @__(@JsonProperty))
|
||||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
@NoArgsConstructor(force = true)
|
@NoArgsConstructor(force = true)
|
||||||
@ToString
|
@ToString
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
package org.springframework.hateoas.mediatype.uber;
|
package org.springframework.hateoas.mediatype.uber;
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.experimental.Wither;
|
import lombok.experimental.Wither;
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
@Value
|
@Value
|
||||||
|
@Getter(onMethod = @__(@JsonProperty))
|
||||||
@Wither(AccessLevel.PACKAGE)
|
@Wither(AccessLevel.PACKAGE)
|
||||||
@JsonInclude(Include.NON_NULL)
|
@JsonInclude(Include.NON_NULL)
|
||||||
class Uber {
|
class Uber {
|
||||||
@@ -74,5 +76,4 @@ class Uber {
|
|||||||
.flatMap(uberData -> uberData.getLinks().stream()) //
|
.flatMap(uberData -> uberData.getLinks().stream()) //
|
||||||
.collect(Links.collector());
|
.collect(Links.collector());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package org.springframework.hateoas.mediatype.uber;
|
|||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.experimental.Wither;
|
import lombok.experimental.Wither;
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ import org.springframework.hateoas.RepresentationModel;
|
|||||||
import org.springframework.hateoas.mediatype.PropertyUtils;
|
import org.springframework.hateoas.mediatype.PropertyUtils;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
@@ -58,6 +60,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
@Value
|
@Value
|
||||||
|
@Getter(onMethod = @__(@JsonProperty))
|
||||||
@Wither(AccessLevel.PACKAGE)
|
@Wither(AccessLevel.PACKAGE)
|
||||||
@JsonInclude(Include.NON_NULL)
|
@JsonInclude(Include.NON_NULL)
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
@@ -105,6 +108,7 @@ class UberData {
|
|||||||
* Don't render if it's {@link UberAction#READ}.
|
* Don't render if it's {@link UberAction#READ}.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@JsonProperty
|
||||||
public UberAction getAction() {
|
public UberAction getAction() {
|
||||||
return action == UberAction.READ ? null : action;
|
return action == UberAction.READ ? null : action;
|
||||||
}
|
}
|
||||||
@@ -113,6 +117,7 @@ class UberData {
|
|||||||
* Use a {@link Boolean} to support returning {@literal null}, and if it is {@literal null}, don't render.
|
* Use a {@link Boolean} to support returning {@literal null}, and if it is {@literal null}, don't render.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@JsonProperty
|
||||||
public Boolean isTemplated() {
|
public Boolean isTemplated() {
|
||||||
|
|
||||||
return Optional.ofNullable(this.url) //
|
return Optional.ofNullable(this.url) //
|
||||||
@@ -124,6 +129,7 @@ class UberData {
|
|||||||
* Use a {@link Boolean} to support returning {@literal null}, and if it is {@literal null}, don't render.
|
* Use a {@link Boolean} to support returning {@literal null}, and if it is {@literal null}, don't render.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@JsonProperty
|
||||||
public Boolean isTransclude() {
|
public Boolean isTransclude() {
|
||||||
return this.transclude ? true : null;
|
return this.transclude ? true : null;
|
||||||
}
|
}
|
||||||
@@ -147,6 +153,10 @@ class UberData {
|
|||||||
.orElse(Collections.emptyList());
|
.orElse(Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasUrl(@Nullable String url) {
|
||||||
|
return ObjectUtils.nullSafeEquals(this.url, url);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple scalar types that can be encoded by value, not type.
|
* Simple scalar types that can be encoded by value, not type.
|
||||||
*/
|
*/
|
||||||
@@ -363,7 +373,7 @@ class UberData {
|
|||||||
|
|
||||||
return affordanceBasedLinks.stream() //
|
return affordanceBasedLinks.stream() //
|
||||||
.flatMap(affordance -> links.stream() //
|
.flatMap(affordance -> links.stream() //
|
||||||
.filter(link -> link.getUrl().equals(affordance.getUrl())) //
|
.filter(data -> data.hasUrl(affordance.getUrl())) //
|
||||||
.map(link -> {
|
.map(link -> {
|
||||||
|
|
||||||
if (link.getAction() == affordance.getAction()) {
|
if (link.getAction() == affordance.getAction()) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
package org.springframework.hateoas.mediatype.uber;
|
package org.springframework.hateoas.mediatype.uber;
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.experimental.Wither;
|
import lombok.experimental.Wither;
|
||||||
@@ -34,6 +35,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
@Value
|
@Value
|
||||||
|
@Getter(onMethod = @__(@JsonProperty))
|
||||||
@Wither(AccessLevel.PACKAGE)
|
@Wither(AccessLevel.PACKAGE)
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
||||||
class UberDocument {
|
class UberDocument {
|
||||||
|
|||||||
@@ -20,11 +20,12 @@ import java.io.Writer;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.MapperFeature;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class to test objects against the Jackson 2.0 {@link ObjectMapper}.
|
* Base class to test objects against the Jackson 2.0 {@link ObjectMapper}.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Jon Brisbin
|
* @author Jon Brisbin
|
||||||
* @author Greg Turnquist
|
* @author Greg Turnquist
|
||||||
@@ -36,6 +37,11 @@ public abstract class AbstractJackson2MarshallingIntegrationTest {
|
|||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
mapper = new ObjectMapper();
|
mapper = new ObjectMapper();
|
||||||
|
mapper.disable(MapperFeature.AUTO_DETECT_CREATORS) //
|
||||||
|
.disable(MapperFeature.AUTO_DETECT_FIELDS) //
|
||||||
|
.disable(MapperFeature.AUTO_DETECT_GETTERS) //
|
||||||
|
.disable(MapperFeature.AUTO_DETECT_IS_GETTERS) //
|
||||||
|
.disable(MapperFeature.AUTO_DETECT_SETTERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String write(Object object) throws Exception {
|
protected String write(Object object) throws Exception {
|
||||||
|
|||||||
@@ -2,9 +2,13 @@ package org.springframework.hateoas.mediatype.hal;
|
|||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@Getter(onMethod = @__(@JsonProperty))
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class SimplePojo {
|
public class SimplePojo {
|
||||||
|
|||||||
Reference in New Issue
Block a user