From 80ff2455a6d1b5baea9083a305e67e43cf6eaa54 Mon Sep 17 00:00:00 2001 From: Strongbeard Date: Wed, 19 Jun 2024 10:40:19 -0400 Subject: [PATCH] Prevent Jackson from unwrapping List in Geometry When a Geometry containing a single list of LngLatAlt within its coordinates list was serialized using an ObjectMapper with SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED enabled the resulting output no longer matched the examples in RFC7946 due to the array brackets for the coordinates list being omitted. This deviation in expected json format prevents deserialization of the output back to the original Geometry. Preventing this feature from activating on the coordinates list in Geometry, even when enabled in the ObjectMapper, resolves the breaking of the idempotent nature of serialization and deserialization by keeping the output as close to the examples in RFC7946 as possible. --- src/main/java/org/geojson/Geometry.java | 3 +++ .../geojson/jackson/MultiLineStringTest.java | 13 ++++++++++++ .../org/geojson/jackson/MultiPoligonTest.java | 20 +++++++++++++++++++ .../java/org/geojson/jackson/PolygonTest.java | 16 ++++++++++++++- 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/geojson/Geometry.java b/src/main/java/org/geojson/Geometry.java index 2f65fcd..4e7d670 100644 --- a/src/main/java/org/geojson/Geometry.java +++ b/src/main/java/org/geojson/Geometry.java @@ -3,8 +3,11 @@ import java.util.ArrayList; import java.util.List; +import com.fasterxml.jackson.annotation.JsonFormat; + public abstract class Geometry extends GeoJsonObject { + @JsonFormat(without = JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED) protected List coordinates = new ArrayList(); public Geometry() { diff --git a/src/test/java/org/geojson/jackson/MultiLineStringTest.java b/src/test/java/org/geojson/jackson/MultiLineStringTest.java index a877b0b..8de6099 100644 --- a/src/test/java/org/geojson/jackson/MultiLineStringTest.java +++ b/src/test/java/org/geojson/jackson/MultiLineStringTest.java @@ -1,6 +1,8 @@ package org.geojson.jackson; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + import org.geojson.LngLatAlt; import org.geojson.MultiLineString; import org.junit.Test; @@ -21,4 +23,15 @@ public void itShouldSerialize() throws Exception { assertEquals("{\"type\":\"MultiLineString\",\"coordinates\":" + "[[[100.0,0.0],[101.0,1.0]],[[102.0,2.0],[103.0,3.0]]]}", mapper.writeValueAsString(multiLineString)); } + + @Test + public void itShouldSerializeIgnoringWriteSingleElemArraysUnwrapped() throws Exception { + ObjectMapper mapper = new ObjectMapper() + .enable(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED); + + MultiLineString multiLineString = new MultiLineString(); + multiLineString.add(Arrays.asList(new LngLatAlt(100, 0), new LngLatAlt(101, 1))); + assertEquals("{\"type\":\"MultiLineString\",\"coordinates\":" + + "[[[100.0,0.0],[101.0,1.0]]]}", mapper.writeValueAsString(multiLineString)); + } } diff --git a/src/test/java/org/geojson/jackson/MultiPoligonTest.java b/src/test/java/org/geojson/jackson/MultiPoligonTest.java index fe60d4e..e44bfa5 100644 --- a/src/test/java/org/geojson/jackson/MultiPoligonTest.java +++ b/src/test/java/org/geojson/jackson/MultiPoligonTest.java @@ -1,6 +1,8 @@ package org.geojson.jackson; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + import org.geojson.LngLatAlt; import org.geojson.MultiPolygon; import org.geojson.Polygon; @@ -27,6 +29,24 @@ public void itShouldSerialize() throws Exception { mapper.writeValueAsString(multiPolygon)); } + @Test + public void itShouldSerializeIgnoringWriteSingleElemArraysUnwrapped() throws Exception { + ObjectMapper mapper = new ObjectMapper() + .enable(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED); + + MultiPolygon multiPolygon = new MultiPolygon(); + multiPolygon.add(new Polygon(new LngLatAlt(102, 2), new LngLatAlt(103, 2), new LngLatAlt(103, 3), + new LngLatAlt(102, 3), new LngLatAlt(102, 2))); + Polygon polygon = new Polygon(MockData.EXTERNAL); + polygon.addInteriorRing(MockData.INTERNAL); + multiPolygon.add(polygon); + assertEquals( + "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[102.0,2.0],[103.0,2.0],[103.0,3.0],[102.0,3.0],[102.0,2.0]]]," + + "[[[100.0,0.0],[101.0,0.0],[101.0,1.0],[100.0,1.0],[100.0,0.0]]," + + "[[100.2,0.2],[100.8,0.2],[100.8,0.8],[100.2,0.8],[100.2,0.2]]]]}", + mapper.writeValueAsString(multiPolygon)); + } + @Test public void itShouldDeserialize() throws Exception { MultiPolygon multiPolygon = mapper.readValue( diff --git a/src/test/java/org/geojson/jackson/PolygonTest.java b/src/test/java/org/geojson/jackson/PolygonTest.java index 6298483..d5a71e7 100644 --- a/src/test/java/org/geojson/jackson/PolygonTest.java +++ b/src/test/java/org/geojson/jackson/PolygonTest.java @@ -1,12 +1,13 @@ package org.geojson.jackson; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + import org.geojson.LngLatAlt; import org.geojson.Polygon; import org.junit.Test; import java.util.Arrays; -import java.util.Collections; import java.util.List; import static org.junit.Assert.assertEquals; @@ -23,6 +24,19 @@ public void itShouldSerialize() throws Exception { mapper.writeValueAsString(polygon)); } + @Test + public void itShouldSerializeIgnoringWriteSingleElemArraysUnwrapped() throws Exception { + ObjectMapper mapper = new ObjectMapper() + .enable(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED) + ; + + Polygon polygon = new Polygon(MockData.EXTERNAL); + String actual = mapper.writeValueAsString(polygon); + assertEquals("{\"type\":\"Polygon\",\"coordinates\":" + + "[[[100.0,0.0],[101.0,0.0],[101.0,1.0],[100.0,1.0],[100.0,0.0]]]}", + actual); + } + @Test public void itShouldSerializeWithHole() throws Exception { Polygon polygon = new Polygon(MockData.EXTERNAL);