#1515 - Fix HAL link serialization issues when Jackson map entry sorting is enabled.
Prior to this commit, the map of links to be rendered would key by LinkRelation. Unfortunately, Jackson requires `Map` keys to implement `Comparable` in case `SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS` is enabled. We now use the link relation's value as key right aways as Strings are comparable out of the box. Switched to use Spring's MultiValueMap to avoid having to deal with the value list initialization ourselves.
This commit is contained in:
@@ -21,7 +21,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
@@ -41,6 +40,8 @@ import org.springframework.hateoas.mediatype.hal.HalConfiguration.RenderSingleLi
|
||||
import org.springframework.hateoas.server.LinkRelationProvider;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
@@ -145,7 +146,7 @@ public class Jackson2HalModule extends SimpleModule {
|
||||
public void serialize(Links value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
|
||||
|
||||
// sort links according to their relation
|
||||
Map<LinkRelation, List<Object>> sortedLinks = new LinkedHashMap<>();
|
||||
MultiValueMap<String, Object> sortedLinks = new LinkedMultiValueMap<>();
|
||||
List<Link> links = new ArrayList<>();
|
||||
|
||||
boolean prefixingRequired = curieProvider != CurieProvider.NONE;
|
||||
@@ -178,10 +179,7 @@ public class Jackson2HalModule extends SimpleModule {
|
||||
curiedLinkPresent = true;
|
||||
}
|
||||
|
||||
sortedLinks //
|
||||
.computeIfAbsent(relation, key -> new ArrayList<>())//
|
||||
.add(toHalLink(link, relation));
|
||||
|
||||
sortedLinks.add(relation.value(), toHalLink(link, relation));
|
||||
links.add(link);
|
||||
}
|
||||
|
||||
@@ -190,12 +188,12 @@ public class Jackson2HalModule extends SimpleModule {
|
||||
Collection<?> curies = curieProvider.getCurieInformation(Links.of(links));
|
||||
|
||||
if (!curies.isEmpty()) {
|
||||
sortedLinks.put(HalLinkRelation.CURIES, new ArrayList<>(curies));
|
||||
sortedLinks.addAll(HalLinkRelation.CURIES.value(), new ArrayList<>(curies));
|
||||
}
|
||||
}
|
||||
|
||||
TypeFactory typeFactory = provider.getConfig().getTypeFactory();
|
||||
JavaType keyType = typeFactory.constructType(LinkRelation.class);
|
||||
JavaType keyType = typeFactory.constructType(String.class);
|
||||
JavaType valueType = typeFactory.constructCollectionType(ArrayList.class, Object.class);
|
||||
JavaType mapType = typeFactory.constructMapType(HashMap.class, keyType, valueType);
|
||||
|
||||
|
||||
@@ -636,6 +636,13 @@ class Jackson2HalIntegrationTest {
|
||||
.isThrownBy(() -> document.read("$.curies", JSONObject.class));
|
||||
}
|
||||
|
||||
@Test // #1515
|
||||
void rendersLinksWhenMapEntrySortingIsEnabled() throws Exception {
|
||||
|
||||
mapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)
|
||||
.writeValueAsString(new RepresentationModel<>().add(Link.of("/href")));
|
||||
}
|
||||
|
||||
@Relation(collectionRelation = "someSample")
|
||||
static class SomeSample {
|
||||
@JsonProperty String name;
|
||||
|
||||
Reference in New Issue
Block a user