Skip to content

Jackson 3.x GeoJson (de-)serializers #5100

@bjornharvold

Description

@bjornharvold

Going to put this here instead of a PR.

With the release of Spring Boot 4 and migration to Jackson 3, Spring Data MongoDb does not yet have support for GeoJson serializers / deserializers for Jackson 3.

Here is that support:

public class GeoJsonModule { public static class serializers extends JacksonModule { @Override public String getModuleName() { return "Spring Data MongoDB GeoJson - Serializers"; } @Override public Version version() { return new Version( 3, 2, 0, (String)null, "org.springframework.data", "spring-data-mongodb-geojson" ); } @Override public void setupModule(SetupContext ctx) { // this.baseModule.setupModule(context); final SimpleSerializers serializers = new SimpleSerializers(); serializers.addSerializer(GeoJsonPoint.class, new GeoJsonPointSerializer()); serializers.addSerializer(GeoJsonMultiPoint.class, new GeoJsonMultiPointSerializer()); serializers.addSerializer(GeoJsonLineString.class, new GeoJsonLineStringSerializer()); serializers.addSerializer(GeoJsonMultiLineString.class, new GeoJsonMultiLineStringSerializer()); serializers.addSerializer(GeoJsonPolygon.class, new GeoJsonPolygonSerializer()); serializers.addSerializer(GeoJsonMultiPolygon.class, new GeoJsonMultiPolygonSerializer()); ctx.addSerializers(serializers); } } public static class deserializers extends JacksonModule { @Override public String getModuleName() { return "Spring Data MongoDB GeoJson - Deserializers"; } @Override public Version version() { return new Version( 3, 2, 0, (String)null, "org.springframework.data", "spring-data-mongodb-geojson" ); } @Override public void setupModule(SetupContext ctx) { // this.baseModule.setupModule(context); final SimpleDeserializers deserializers = new SimpleDeserializers(); deserializers.addDeserializer(GeoJsonPoint.class, new GeoJsonPointDeserializer()); deserializers.addDeserializer(GeoJsonMultiPoint.class, new GeoJsonMultiPointDeserializer()); deserializers.addDeserializer(GeoJsonLineString.class, new GeoJsonLineStringDeserializer()); deserializers.addDeserializer(GeoJsonMultiLineString.class, new GeoJsonMultiLineStringDeserializer()); deserializers.addDeserializer(GeoJsonPolygon.class, new GeoJsonPolygonDeserializer()); deserializers.addDeserializer(GeoJsonMultiPolygon.class, new GeoJsonMultiPolygonDeserializer()); ctx.addDeserializers(deserializers); } } private abstract static class GeoJsonDeserializer<T extends GeoJson<?>> extends ValueDeserializer<T> { public @Nullable T deserialize(JsonParser jp, @Nullable DeserializationContext ctxt) throws JacksonException { JsonNode node = (JsonNode)jp.readValueAsTree(); JsonNode coordinates = node.get("coordinates"); return (T)(coordinates != null && coordinates.isArray() ? this.doDeserialize((ArrayNode)coordinates) : null); } protected abstract @Nullable T doDeserialize(ArrayNode coordinates); protected @Nullable GeoJsonPoint toGeoJsonPoint(@Nullable ArrayNode node) { return node == null ? null : new GeoJsonPoint(node.get(0).asDouble(), node.get(1).asDouble()); } protected @Nullable Point toPoint(@Nullable ArrayNode node) { return node == null ? null : new Point(node.get(0).asDouble(), node.get(1).asDouble()); } protected List<Point> toPoints(@Nullable ArrayNode node) { if (node == null) { return Collections.emptyList(); } else { List<Point> points = new ArrayList(node.size()); for(JsonNode coordinatePair : node) { if (coordinatePair.isArray()) { points.add(this.toPoint((ArrayNode)coordinatePair)); } } return points; } } protected GeoJsonLineString toLineString(ArrayNode node) { return new GeoJsonLineString(this.toPoints(node)); } } private static class GeoJsonPointDeserializer extends GeoJsonDeserializer<GeoJsonPoint> { protected @Nullable GeoJsonPoint doDeserialize(ArrayNode coordinates) { return this.toGeoJsonPoint(coordinates); } } private static class GeoJsonLineStringDeserializer extends GeoJsonDeserializer<GeoJsonLineString> { protected GeoJsonLineString doDeserialize(ArrayNode coordinates) { return new GeoJsonLineString(this.toPoints(coordinates)); } } private static class GeoJsonMultiPointDeserializer extends GeoJsonDeserializer<GeoJsonMultiPoint> { protected GeoJsonMultiPoint doDeserialize(ArrayNode coordinates) { return new GeoJsonMultiPoint(this.toPoints(coordinates)); } } private static class GeoJsonMultiLineStringDeserializer extends GeoJsonDeserializer<GeoJsonMultiLineString> { protected GeoJsonMultiLineString doDeserialize(ArrayNode coordinates) { List<GeoJsonLineString> lines = new ArrayList(coordinates.size()); for(JsonNode lineString : coordinates) { if (lineString.isArray()) { lines.add(this.toLineString((ArrayNode)lineString)); } } return new GeoJsonMultiLineString(lines); } } private static class GeoJsonPolygonDeserializer extends GeoJsonDeserializer<GeoJsonPolygon> { protected @Nullable GeoJsonPolygon doDeserialize(ArrayNode coordinates) { Iterator var2 = coordinates.iterator(); if (var2.hasNext()) { JsonNode ring = (JsonNode)var2.next(); return new GeoJsonPolygon(this.toPoints((ArrayNode)ring)); } else { return null; } } } private static class GeoJsonMultiPolygonDeserializer extends GeoJsonDeserializer<GeoJsonMultiPolygon> { protected GeoJsonMultiPolygon doDeserialize(ArrayNode coordinates) { List<GeoJsonPolygon> polygones = new ArrayList(coordinates.size()); for(JsonNode polygon : coordinates) { for(JsonNode ring : polygon) { polygones.add(new GeoJsonPolygon(this.toPoints((ArrayNode)ring))); } } return new GeoJsonMultiPolygon(polygones); } } private abstract static class GeoJsonSerializer<T extends GeoJson<? extends Iterable>> extends ValueSerializer<T> { @Override public void serialize(T shape, JsonGenerator jsonGenerator, SerializationContext ctxt) throws JacksonException { jsonGenerator.writeStartObject(); jsonGenerator.writeStringProperty("type", shape.getType()); jsonGenerator.writeArrayPropertyStart("coordinates"); this.doSerialize(shape, jsonGenerator); jsonGenerator.writeEndArray(); jsonGenerator.writeEndObject(); } protected abstract void doSerialize(T shape, JsonGenerator jsonGenerator) throws JacksonException; protected void writePoint(Point point, JsonGenerator jsonGenerator) throws JacksonException { jsonGenerator.writeStartArray(); this.writeRawCoordinates(point, jsonGenerator); jsonGenerator.writeEndArray(); } protected void writeRawCoordinates(Point point, JsonGenerator jsonGenerator) throws JacksonException { jsonGenerator.writeNumber(point.getX()); jsonGenerator.writeNumber(point.getY()); } protected void writeLine(Iterable<Point> points, JsonGenerator jsonGenerator) throws JacksonException { jsonGenerator.writeStartArray(); this.writeRawLine(points, jsonGenerator); jsonGenerator.writeEndArray(); } protected void writeRawLine(Iterable<Point> points, JsonGenerator jsonGenerator) throws JacksonException { for(Point point : points) { this.writePoint(point, jsonGenerator); } } } static class GeoJsonPointSerializer extends GeoJsonSerializer<GeoJsonPoint> { protected void doSerialize(GeoJsonPoint value, JsonGenerator jsonGenerator) throws JacksonException { this.writeRawCoordinates(value, jsonGenerator); } } static class GeoJsonLineStringSerializer extends GeoJsonSerializer<GeoJsonLineString> { protected void doSerialize(GeoJsonLineString value, JsonGenerator jsonGenerator) throws JacksonException { this.writeRawLine(value.getCoordinates(), jsonGenerator); } } static class GeoJsonMultiPointSerializer extends GeoJsonSerializer<GeoJsonMultiPoint> { protected void doSerialize(GeoJsonMultiPoint value, JsonGenerator jsonGenerator) throws JacksonException { this.writeRawLine(value.getCoordinates(), jsonGenerator); } } static class GeoJsonMultiLineStringSerializer extends GeoJsonSerializer<GeoJsonMultiLineString> { protected void doSerialize(GeoJsonMultiLineString value, JsonGenerator jsonGenerator) throws JacksonException { for(GeoJsonLineString lineString : value.getCoordinates()) { this.writeLine(lineString.getCoordinates(), jsonGenerator); } } } static class GeoJsonPolygonSerializer extends GeoJsonSerializer<GeoJsonPolygon> { protected void doSerialize(GeoJsonPolygon value, JsonGenerator jsonGenerator) throws JacksonException { for(GeoJsonLineString lineString : value.getCoordinates()) { this.writeLine(lineString.getCoordinates(), jsonGenerator); } } } static class GeoJsonMultiPolygonSerializer extends GeoJsonSerializer<GeoJsonMultiPolygon> { protected void doSerialize(GeoJsonMultiPolygon value, JsonGenerator jsonGenerator) throws JacksonException { for(GeoJsonPolygon polygon : value.getCoordinates()) { jsonGenerator.writeStartArray(); for(GeoJsonLineString lineString : polygon.getCoordinates()) { this.writeLine(lineString.getCoordinates(), jsonGenerator); } jsonGenerator.writeEndArray(); } } } } 

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions