#29 - Added support for HAL-style representation of Links.
Added Jackson 1 and 2 modules to render Link objects in a HAL-compliant way. Introduced custom Jackson mixins to avoid introducing new value objects for the representation model. The rendering can be activated by simply registering Jackson1HalModule or Jackson2HalModule with the Jackson ObjectMapper.
This commit is contained in:
committed by
Oliver Gierke
parent
c7396c24a9
commit
7af38348a9
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright 2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.hateoas.hal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.codehaus.jackson.JsonGenerationException;
|
||||
import org.codehaus.jackson.JsonGenerator;
|
||||
import org.codehaus.jackson.Version;
|
||||
import org.codehaus.jackson.map.BeanProperty;
|
||||
import org.codehaus.jackson.map.ContextualSerializer;
|
||||
import org.codehaus.jackson.map.JsonMappingException;
|
||||
import org.codehaus.jackson.map.JsonSerializer;
|
||||
import org.codehaus.jackson.map.SerializationConfig;
|
||||
import org.codehaus.jackson.map.SerializerProvider;
|
||||
import org.codehaus.jackson.map.TypeSerializer;
|
||||
import org.codehaus.jackson.map.module.SimpleModule;
|
||||
import org.codehaus.jackson.map.ser.std.ContainerSerializerBase;
|
||||
import org.codehaus.jackson.map.ser.std.MapSerializer;
|
||||
import org.codehaus.jackson.map.type.TypeFactory;
|
||||
import org.codehaus.jackson.type.JavaType;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
|
||||
/**
|
||||
* Jackson 1 module implementation to render {@link Link} and {@link ResourceSupport} instances in HAL compatible JSON.
|
||||
*
|
||||
* @author Alexander Baetz
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class Jackson1HalModule extends SimpleModule {
|
||||
|
||||
/**
|
||||
* Creates a new {@link Jackson1HalModule}.
|
||||
*/
|
||||
public Jackson1HalModule() {
|
||||
|
||||
super("json-hal-module", new Version(1, 0, 0, null));
|
||||
|
||||
setMixInAnnotation(Link.class, LinkMixin.class);
|
||||
setMixInAnnotation(ResourceSupport.class, ResourceSupportMixin.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom {@link JsonSerializer} to render Link instances in HAL compatible JSON.
|
||||
*
|
||||
* @author Alexander Baetz
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public static class HalLinkListSerializer extends ContainerSerializerBase<List<Link>> implements
|
||||
ContextualSerializer<List<Link>> {
|
||||
|
||||
private final BeanProperty property;
|
||||
|
||||
/**
|
||||
* Creates a new {@link HalLinkListSerializer}.
|
||||
*/
|
||||
public HalLinkListSerializer() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public HalLinkListSerializer(BeanProperty property) {
|
||||
super(List.class, false);
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.codehaus.jackson.map.ser.std.SerializerBase#serialize(java.lang.Object, org.codehaus.jackson.JsonGenerator, org.codehaus.jackson.map.SerializerProvider)
|
||||
*/
|
||||
@Override
|
||||
public void serialize(List<Link> value, JsonGenerator jgen, SerializerProvider provider) throws IOException,
|
||||
JsonGenerationException {
|
||||
|
||||
// sort links according to their relation
|
||||
Map<String, List<Link>> sortedLinks = new HashMap<String, List<Link>>();
|
||||
|
||||
for (Link link : value) {
|
||||
|
||||
if (sortedLinks.get(link.getRel()) == null) {
|
||||
sortedLinks.put(link.getRel(), new ArrayList<Link>());
|
||||
}
|
||||
|
||||
sortedLinks.get(link.getRel()).add(link);
|
||||
}
|
||||
|
||||
TypeFactory typeFactory = provider.getConfig().getTypeFactory();
|
||||
JavaType keyType = typeFactory.uncheckedSimpleType(String.class);
|
||||
JavaType valueType = typeFactory.constructCollectionType(ArrayList.class, Link.class);
|
||||
JavaType mapType = typeFactory.constructMapType(HashMap.class, keyType, valueType);
|
||||
|
||||
MapSerializer serializer = MapSerializer.construct(new String[] {}, mapType, true, null, null,
|
||||
provider.findKeySerializer(keyType, null), new OptionalListSerializer(property));
|
||||
|
||||
serializer.serialize(sortedLinks, jgen, provider);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.codehaus.jackson.map.ContextualSerializer#createContextual(org.codehaus.jackson.map.SerializationConfig, org.codehaus.jackson.map.BeanProperty)
|
||||
*/
|
||||
@Override
|
||||
public JsonSerializer<List<Link>> createContextual(SerializationConfig config, BeanProperty property)
|
||||
throws JsonMappingException {
|
||||
return new HalLinkListSerializer(property);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.codehaus.jackson.map.ser.std.ContainerSerializerBase#_withValueTypeSerializer(org.codehaus.jackson.map.TypeSerializer)
|
||||
*/
|
||||
@Override
|
||||
public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom {@link JsonSerializer} to render Link instances in HAL compatible JSON. Renders the {@link Link} as
|
||||
* immediate object if we have a single one or as array if we have multiple ones.
|
||||
*
|
||||
* @author Alexander Baetz
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public static class OptionalListSerializer extends ContainerSerializerBase<Object> {
|
||||
|
||||
private final BeanProperty property;
|
||||
private JsonSerializer<Object> serializer;
|
||||
|
||||
public OptionalListSerializer() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public OptionalListSerializer(BeanProperty property) {
|
||||
|
||||
super(List.class, false);
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.codehaus.jackson.map.ser.std.ContainerSerializerBase#_withValueTypeSerializer(org.codehaus.jackson.map.TypeSerializer)
|
||||
*/
|
||||
@Override
|
||||
public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.codehaus.jackson.map.ser.std.SerializerBase#serialize(java.lang.Object, org.codehaus.jackson.JsonGenerator, org.codehaus.jackson.map.SerializerProvider)
|
||||
*/
|
||||
@Override
|
||||
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException,
|
||||
JsonGenerationException {
|
||||
|
||||
List<?> list = (List<?>) value;
|
||||
|
||||
if (list.size() == 1) {
|
||||
serializeContents(list.iterator(), jgen, provider);
|
||||
return;
|
||||
}
|
||||
|
||||
jgen.writeStartArray();
|
||||
serializeContents(list.iterator(), jgen, provider);
|
||||
jgen.writeEndArray();
|
||||
}
|
||||
|
||||
private void serializeContents(Iterator<?> value, JsonGenerator jgen, SerializerProvider provider)
|
||||
throws IOException, JsonGenerationException {
|
||||
|
||||
while (value.hasNext()) {
|
||||
Object elem = value.next();
|
||||
if (elem == null) {
|
||||
provider.defaultSerializeNull(jgen);
|
||||
} else {
|
||||
if (serializer == null) {
|
||||
serializer = provider.findValueSerializer(elem.getClass(), property);
|
||||
}
|
||||
serializer.serialize(elem, jgen, provider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Copyright 2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.hateoas.hal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerationException;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.Version;
|
||||
import com.fasterxml.jackson.databind.BeanProperty;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.databind.ser.ContainerSerializer;
|
||||
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
|
||||
import com.fasterxml.jackson.databind.ser.std.MapSerializer;
|
||||
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||
|
||||
/**
|
||||
* Jackson 2 module implementation to render {@link Link} and {@link ResourceSupport} instances in HAL compatible JSON.
|
||||
*
|
||||
* @author Alexander Baetz
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class Jackson2HalModule extends SimpleModule {
|
||||
|
||||
private static final long serialVersionUID = 7806951456457932384L;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public Jackson2HalModule() {
|
||||
|
||||
super("json-hal-module", new Version(1, 0, 0, null));
|
||||
|
||||
setMixInAnnotation(Link.class, LinkMixin.class);
|
||||
setMixInAnnotation(ResourceSupport.class, ResourceSupportMixin.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom {@link JsonSerializer} to render Link instances in HAL compatible JSON.
|
||||
*
|
||||
* @author Alexander Baetz
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public static class HalLinkListSerializer extends ContainerSerializer<List<Link>> implements ContextualSerializer {
|
||||
|
||||
private final BeanProperty property;
|
||||
|
||||
public HalLinkListSerializer() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public HalLinkListSerializer(BeanProperty property) {
|
||||
|
||||
super(List.class, false);
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.ser.std.StdSerializer#serialize(java.lang.Object, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider)
|
||||
*/
|
||||
@Override
|
||||
public void serialize(List<Link> value, JsonGenerator jgen, SerializerProvider provider) throws IOException,
|
||||
JsonGenerationException {
|
||||
|
||||
// sort links according to their relation
|
||||
Map<String, List<Link>> sortedLinks = new HashMap<String, List<Link>>();
|
||||
for (Link link : value) {
|
||||
if (sortedLinks.get(link.getRel()) == null) {
|
||||
sortedLinks.put(link.getRel(), new ArrayList<Link>());
|
||||
}
|
||||
sortedLinks.get(link.getRel()).add(link);
|
||||
}
|
||||
|
||||
TypeFactory typeFactory = provider.getConfig().getTypeFactory();
|
||||
JavaType keyType = typeFactory.uncheckedSimpleType(String.class);
|
||||
JavaType valueType = typeFactory.constructCollectionType(ArrayList.class, Link.class);
|
||||
JavaType mapType = typeFactory.constructMapType(HashMap.class, keyType, valueType);
|
||||
|
||||
MapSerializer serializer = MapSerializer.construct(new String[] {}, mapType, true, null,
|
||||
provider.findKeySerializer(keyType, null), new OptionalListJackson2Serializer(property));
|
||||
|
||||
serializer.serialize(sortedLinks, jgen, provider);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.ser.ContextualSerializer#createContextual(com.fasterxml.jackson.databind.SerializerProvider, com.fasterxml.jackson.databind.BeanProperty)
|
||||
*/
|
||||
@Override
|
||||
public JsonSerializer<?> createContextual(SerializerProvider provider, BeanProperty property)
|
||||
throws JsonMappingException {
|
||||
return new HalLinkListSerializer(property);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.ser.ContainerSerializer#getContentType()
|
||||
*/
|
||||
@Override
|
||||
public JavaType getContentType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.ser.ContainerSerializer#getContentSerializer()
|
||||
*/
|
||||
@Override
|
||||
public JsonSerializer<?> getContentSerializer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.ser.ContainerSerializer#isEmpty(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty(List<Link> value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.ser.ContainerSerializer#hasSingleElement(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean hasSingleElement(List<Link> value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.ser.ContainerSerializer#_withValueTypeSerializer(com.fasterxml.jackson.databind.jsontype.TypeSerializer)
|
||||
*/
|
||||
@Override
|
||||
protected ContainerSerializer<?> _withValueTypeSerializer(TypeSerializer vts) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom {@link JsonSerializer} to render Link instances in HAL compatible JSON. Renders the {@link Link} as
|
||||
* immediate object if we have a single one or as array if we have multiple ones.
|
||||
*
|
||||
* @author Alexander Baetz
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public static class OptionalListJackson2Serializer extends ContainerSerializer<Object> implements
|
||||
ContextualSerializer {
|
||||
|
||||
private final BeanProperty property;
|
||||
private JsonSerializer<Object> serializer;
|
||||
|
||||
public OptionalListJackson2Serializer() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link OptionalListJackson2Serializer} using the given {@link BeanProperty}.
|
||||
*
|
||||
* @param property
|
||||
*/
|
||||
public OptionalListJackson2Serializer(BeanProperty property) {
|
||||
|
||||
super(List.class, false);
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.ser.ContainerSerializer#_withValueTypeSerializer(com.fasterxml.jackson.databind.jsontype.TypeSerializer)
|
||||
*/
|
||||
@Override
|
||||
public ContainerSerializer<?> _withValueTypeSerializer(TypeSerializer vts) {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.ser.std.StdSerializer#serialize(java.lang.Object, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider)
|
||||
*/
|
||||
@Override
|
||||
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException,
|
||||
JsonGenerationException {
|
||||
|
||||
List<?> list = (List<?>) value;
|
||||
|
||||
if (list.size() == 1) {
|
||||
serializeContents(list.iterator(), jgen, provider);
|
||||
return;
|
||||
}
|
||||
|
||||
jgen.writeStartArray();
|
||||
serializeContents(list.iterator(), jgen, provider);
|
||||
jgen.writeEndArray();
|
||||
}
|
||||
|
||||
private void serializeContents(Iterator<?> value, JsonGenerator jgen, SerializerProvider provider)
|
||||
throws IOException, JsonGenerationException {
|
||||
|
||||
while (value.hasNext()) {
|
||||
Object elem = value.next();
|
||||
if (elem == null) {
|
||||
provider.defaultSerializeNull(jgen);
|
||||
} else {
|
||||
if (serializer == null) {
|
||||
serializer = provider.findValueSerializer(elem.getClass(), property);
|
||||
}
|
||||
serializer.serialize(elem, jgen, provider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.ser.ContainerSerializer#getContentSerializer()
|
||||
*/
|
||||
@Override
|
||||
public JsonSerializer<?> getContentSerializer() {
|
||||
return serializer;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.ser.ContainerSerializer#getContentType()
|
||||
*/
|
||||
@Override
|
||||
public JavaType getContentType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.ser.ContainerSerializer#hasSingleElement(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean hasSingleElement(Object arg0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.ser.ContainerSerializer#isEmpty(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty(Object arg0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.ser.ContextualSerializer#createContextual(com.fasterxml.jackson.databind.SerializerProvider, com.fasterxml.jackson.databind.BeanProperty)
|
||||
*/
|
||||
@Override
|
||||
public JsonSerializer<?> createContextual(SerializerProvider provider, BeanProperty property)
|
||||
throws JsonMappingException {
|
||||
return new OptionalListJackson2Serializer(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
22
src/main/java/org/springframework/hateoas/hal/LinkMixin.java
Normal file
22
src/main/java/org/springframework/hateoas/hal/LinkMixin.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.hateoas.hal;
|
||||
|
||||
import org.springframework.hateoas.Link;
|
||||
|
||||
class LinkMixin extends Link {
|
||||
private static final long serialVersionUID = 4720588561299667409L;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.hateoas.hal;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
|
||||
abstract class ResourceSupportMixin extends ResourceSupport {
|
||||
|
||||
@Override
|
||||
@XmlElement(name = "link")
|
||||
@org.codehaus.jackson.annotate.JsonProperty("_links")
|
||||
@com.fasterxml.jackson.annotation.JsonProperty("_links")
|
||||
@org.codehaus.jackson.map.annotate.JsonSerialize(include = org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion.NON_EMPTY, using = org.springframework.hateoas.hal.Jackson1HalModule.HalLinkListSerializer.class)
|
||||
@com.fasterxml.jackson.databind.annotation.JsonSerialize(include = com.fasterxml.jackson.databind.annotation.JsonSerialize.Inclusion.NON_EMPTY, using = org.springframework.hateoas.hal.Jackson2HalModule.HalLinkListSerializer.class)
|
||||
public abstract List<Link> getLinks();
|
||||
}
|
||||
Reference in New Issue
Block a user