In my PostgreSQL 9.3 + PostGIS 2.1.5 I have a table PLACE
with a column coordinates
of type Geometry(Point,26910)
.
I want to m
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 coodinates.
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 geomertry;
@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 getGeomertry() {
return geomertry;
}
public void setGeomertry(Geometry geomertry) {
this.geomertry = geomertry;
}
}
My table had these 2 columns:
id | integer
geometry | geometry(Geometry,4326) |
The problem doesn't appear to be related to PostgreSQL. It appears that your POJO has a backreference, which means that your mapper doesn't know how to handle it. You need to explicitly define the recursive relationships so that the mapper knows when to stop. (My Goto link --> http://vard-lokkur.blogspot.com/2010/10/json-jackson-to-rescue.html)
This serialization/deserialization also worked fine for me.
https://github.com/bedatadriven/jackson-datatype-jts
If you don't want to add the annotation on all your fields that are using a Point, you can also use the @JsonComponent to register your JsonSerializer and JsonDeserializer.
@JsonComponent
public class PointSerializer extends JsonSerializer<com.vividsolutions.jts.geom.Point>{
@Override
public void serialize(com.vividsolutions.jts.geom.Point value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeNumberField("lat", value.getY());
gen.writeNumberField("lon", value.getX());
gen.writeEndObject();
}
}