Map a PostGIS geometry point field with Hibernate on Spring Boot
Finally I discovered that my configuration is ok and might be Jackson that cannot manage Point
data type correctly. So I customized its JSON serialization and deserialization:
add these annotations to our
coordinates
field:@JsonSerialize(using = PointToJsonSerializer.class)@JsonDeserialize(using = JsonToPointDeserializer.class)
create such serializer:
import java.io.IOException;import com.fasterxml.jackson.core.JsonGenerator;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.JsonSerializer;import com.fasterxml.jackson.databind.SerializerProvider;import com.vividsolutions.jts.geom.Point;public class PointToJsonSerializer extends JsonSerializer<Point> { @Override public void serialize(Point value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { String jsonValue = "null"; try { if(value != null) { double lat = value.getY(); double lon = value.getX(); jsonValue = String.format("POINT (%s %s)", lat, lon); } } catch(Exception e) {} jgen.writeString(jsonValue); }}
create such deserializer:
import java.io.IOException;import com.fasterxml.jackson.core.JsonParser;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.DeserializationContext;import com.fasterxml.jackson.databind.JsonDeserializer;import com.vividsolutions.jts.geom.Coordinate;import com.vividsolutions.jts.geom.GeometryFactory;import com.vividsolutions.jts.geom.Point;import com.vividsolutions.jts.geom.PrecisionModel;public class JsonToPointDeserializer extends JsonDeserializer<Point> { private final static GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 26910); @Override public Point deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { try { String text = jp.getText(); if(text == null || text.length() <= 0) return null; String[] coordinates = text.replaceFirst("POINT ?\\(", "").replaceFirst("\\)", "").split(" "); double lat = Double.parseDouble(coordinates[0]); double lon = Double.parseDouble(coordinates[1]); Point point = geometryFactory.createPoint(new Coordinate(lat, lon)); return point; } catch(Exception e){ return null; } }}
Maybe you can also use this serializer and this deserializer, available here.
The solutions above helped me to fix the problem. I simplify it so other people can understand.
I included this library in my pom.xml:
<dependency> <groupId>com.bedatadriven</groupId> <artifactId>jackson-datatype-jts</artifactId> <version>2.2</version></dependency>
This is the POJO object I used. Then I was able to get the REST call to work without the envelope error and proper coordinates.
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;@Entity@Table(name = "boundary")public class Boundary { private int id; private Geometry geometry; @Id public int getId() { return ogc_fid; } public void setId(int id) { this.id = id; } @JsonSerialize(using = GeometrySerializer.class) @JsonDeserialize(using = GeometryDeserializer.class) @Column(name = "geometry", columnDefinition = "Geometry") public Geometry getGeometry() { return geometry; } public void setGeometry(Geometry geometry) { this.geometry = geometry; }}
My table had these 2 columns:
id | integer geometry | geometry(Geometry,4326) |
This serialization/deserialization also worked fine for me.