Question

I'm trying to use the JTS library and I'm having a strange problem with serializing a class that has a Point property.

import java.io.IOException;
import java.io.Serializable;

import com.owlike.genson.Genson;
import com.owlike.genson.TransformationException;
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 TestJTS implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 7778701490986272036L;
    protected Point point = null;

    public TestJTS() {
        super();
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        TestJTS test = new TestJTS();
        GeometryFactory gf = new GeometryFactory(new PrecisionModel(), 4326);
        Coordinate coordinate = new Coordinate(10.0, 100.1);
        Point point = gf.createPoint(coordinate);
        test.setPoint(point);

        System.out.println("Point: " + test.getPoint());

        Genson genson = new Genson();
        try {
            String json = genson.serialize(test);
            System.out.println(json);

        } catch (TransformationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public Point getPoint() {
        return point;
    }

    public void setPoint(Point point) {
        this.point = point;
    }
}

This minimal example below gives me exceptions but I don't understand why. Is my code wrong? Am I making an incorrect assumption about how to use the JTS library?

Point: POINT (10 100.1)
com.owlike.genson.TransformationException: Could not serialize property 'point' from class TestJTS
    at com.owlike.genson.reflect.PropertyAccessor.couldNotSerialize(PropertyAccessor.java:48)
    at com.owlike.genson.reflect.PropertyAccessor.serialize(PropertyAccessor.java:31)
    at com.owlike.genson.reflect.BeanDescriptor.serialize(BeanDescriptor.java:87)
    at com.owlike.genson.convert.NullConverter$NullConverterWrapper.serialize(NullConverter.java:51)
    at com.owlike.genson.Genson.serialize(Genson.java:341)
    at com.owlike.genson.Genson.serialize(Genson.java:222)
    at TestJTS.main(TestJTS.java:40)
Caused by: com.owlike.genson.TransformationException: Could not serialize property 'boundary' from class com.vividsolutions.jts.geom.Point
    at com.owlike.genson.reflect.PropertyAccessor.couldNotSerialize(PropertyAccessor.java:48)
    at com.owlike.genson.reflect.PropertyAccessor.serialize(PropertyAccessor.java:31)
    at com.owlike.genson.reflect.BeanDescriptor.serialize(BeanDescriptor.java:87)
    at com.owlike.genson.convert.NullConverter$NullConverterWrapper.serialize(NullConverter.java:51)
    at com.owlike.genson.convert.CircularClassReferenceConverterFactory$CircularConverter.serialize(CircularClassReferenceConverterFactory.java:30)
    at com.owlike.genson.reflect.PropertyAccessor.serialize(PropertyAccessor.java:29)
    ... 5 more
Caused by: com.owlike.genson.TransformationRuntimeException: Could not access value of property named 'boundary' using accessor public abstract com.vividsolutions.jts.geom.Geometry com.vividsolutions.jts.geom.Geometry.getBoundary() from class com.vividsolutions.jts.geom.Geometry
    at com.owlike.genson.reflect.PropertyAccessor.couldNotAccess(PropertyAccessor.java:42)
    at com.owlike.genson.reflect.PropertyAccessor$MethodAccessor.access(PropertyAccessor.java:72)
    at com.owlike.genson.reflect.PropertyAccessor.serialize(PropertyAccessor.java:26)
    at com.owlike.genson.reflect.BeanDescriptor.serialize(BeanDescriptor.java:87)
    at com.owlike.genson.convert.NullConverter$NullConverterWrapper.serialize(NullConverter.java:51)
    at com.owlike.genson.convert.CircularClassReferenceConverterFactory$CircularConverter.serialize(CircularClassReferenceConverterFactory.java:30)
    at com.owlike.genson.reflect.PropertyAccessor.serialize(PropertyAccessor.java:29)
    ... 9 more
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.owlike.genson.reflect.PropertyAccessor$MethodAccessor.access(PropertyAccessor.java:66)
    ... 14 more
Caused by: java.lang.IllegalArgumentException: This method does not support GeometryCollection arguments
    at com.vividsolutions.jts.geom.Geometry.checkNotGeometryCollection(Geometry.java:1782)
    at com.vividsolutions.jts.geom.GeometryCollection.getBoundary(GeometryCollection.java:154)
    ... 19 more

Was it helpful?

Solution

The problem here is that Genson is trying to serialize your point based on its getter methods and public fields, this does not seem to mix well with JTS. The best solution would be to write a custom converter that will be built using a factory, this allows you to delegate some stuff to existing mechanism.

class JTSPointConverterFactory implements Factory<Converter<Point>> {

    @Override public Converter<Point> create(Type type,
            Genson genson) {
        final Converter<Coordinate> coordianteConverter = genson.provideConverter(Coordinate.class);

        Converter<Point> pointConverter = new Converter<Point>() {
            private final GeometryFactory gf = new GeometryFactory(new PrecisionModel(), 4326);

            @Override public void serialize(Point point, ObjectWriter writer,
                    Context ctx) throws TransformationException, IOException {
                Coordinate coordinate = point.getCoordinate();

                writer.beginObject()
                        .writeName("x").writeValue(coordinate.x)
                        .writeName("y").writeValue(coordinate.y);

                if (!Double.isNaN(coordinate.z)) 
                    writer.writeName("z").writeValue(coordinate.z);

                writer.endObject();
            }

            @Override public Point deserialize(ObjectReader reader, Context ctx)
                    throws TransformationException, IOException {
                // just delegate to gensons Coordiante converter the deserialization
                return gf.createPoint(coordianteConverter.deserialize(reader, ctx));
            }
        };
        return pointConverter;
    }

}

// now register your factory
Genson genson = new Genson.Builder()
                            .withConverterFactory(new JTSPointConverterFactory())
                            .create();

genson.serialize(testJts);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top