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
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.
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(); }
}
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>