Jackson deserialize GeoJson Point in Spring Boot

前端 未结 3 1823
日久生厌
日久生厌 2020-12-18 06:27

I have a @Entity model that has a property of type com.vividsolutions.jts.geom.Point. When I try to render this model in a @RestController

相关标签:
3条回答
  • 2020-12-18 06:53

    As of 2020 most of the JTS libraries are outdated and no longer work. I found one fork on Maven Central that was updated recently and it worked flawlessly with jackson-core:2.10.0 and jts-core:1.16.1:

    implementation 'org.n52.jackson:jackson-datatype-jts:1.2.4'

    Sample usage:

        @Test
        void testJson() throws IOException {
    
            var objectMapper = new ObjectMapper();
            objectMapper.registerModule(new JtsModule());
    
            GeometryFactory gf = new GeometryFactory();
            Point point = gf.createPoint(new Coordinate(1.2345678, 2.3456789));
    
            String geojson = objectMapper.writeValueAsString(point);
    
            InputStream targetStream = new ByteArrayInputStream(geojson.getBytes());
            Point point2 = objectMapper.readValue(targetStream, Point.class);
    
            assertEquals(point, point2);
        }
    

    You don't need to use any annotations on class fields or register new Spring Beans, just register the JTS module with Jackson.

    0 讨论(0)
  • 2020-12-18 07:00

    The above workaround using JTSModule results in an internal SpringBoot error for me. I was able to solve this issue by making sure the getter methods of my Entity are returning String types.

    @Entity
    public class MyClassWithGeom {
    
        @Id
        @GeneratedValue
        private Long id;
        private Point centre;
        private Polygon boundary;
    
        private MyClassWithGeom() {}
    
        public MyClassWithGeom(String centreLat, String centreLng, Double[]... boundaryCoords) {
            String wkt = "POINT (" + centreLat + " " + centreLng + ")";
            StringBuilder builder = new StringBuilder("POLYGON (( ");
    
            for(int i=0;i<boundaryCoords.length;i++) {
                Double[] coord = boundaryCoords[i];
                if (i < boundaryCoords.length - 1)
                    builder = builder.append(coord[0]).append(" ").append(coord[1]).append(", ");
                else
                    builder = builder.append(coord[0]).append(" ").append(coord[1]).append(" ))");
            }
    
            try {
                this.centre = (Point) this.wktToGeometry(wkt);
                logger.info(this.centre.toString());
                this.boundary = (Polygon) this.wktToGeometry(builder.toString());
                logger.info(this.boundary.toString());
            }
            catch (ParseException pe) {
                logger.error(pe.getMessage());
                logger.error("Invalid WKT: " + wkt);
            }
        }
    
        public Geometry wktToGeometry(String wellKnownText) throws ParseException {
            return new WKTReader().read(wellKnownText);
        }
    
        public String getCentre() { return centre.toString(); }
    
        public String getName() { return name; }
    
        public String getBoundary() { return boundary.toString(); }
    }
    
    0 讨论(0)
  • 2020-12-18 07:02

    Maybe you should tag your geometric attribute with @JsonSerialize and @JsonDeserialize. Like this:

    import com.bedatadriven.jackson.datatype.jts.serialization.GeometryDeserializer;
    import com.bedatadriven.jackson.datatype.jts.serialization.GeometrySerializer;
    import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
    import com.fasterxml.jackson.databind.annotation.JsonSerialize;
    import com.vividsolutions.jts.geom.Geometry;
    import fr.info.groloc.entity.json.GreffeDeserializer;
    
    import javax.persistence.Entity;
    
    @Entity
    public class Table
    {
        @JsonSerialize(using = GeometrySerializer.class)
        @JsonDeserialize(contentUsing = GeometryDeserializer.class)
        private Geometry coord;
        // ...
    }
    

    If you are using Spring-Boot you only need for:

    import com.bedatadriven.jackson.datatype.jts.JtsModule;
    // ...
    @Bean
    public JtsModule jtsModule()
    {
        return new JtsModule();
    }
    

    As Dave said you need to add this dependency to your pom.xml:

    <dependency>
        <groupId>com.bedatadriven</groupId>
        <artifactId>jackson-datatype-jts</artifactId>
        <version>2.4</version>
    </dependency>
    
    0 讨论(0)
提交回复
热议问题