我正在尝试使用JTS库,并且在序列化具有Point属性的类时遇到了一个奇怪的问题。

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;
    }
}


下面的这个最小示例为我提供了例外,但我不明白为什么。我的代码错了吗?我对使用JTS库是否有错误的假设?

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

最佳答案

这里的问题是Genson试图根据其getter方法和公共字段来序列化您的点,这似乎与JTS混合得不好。最好的解决方案是编写一个将使用工厂构建的自定义转换器,这使您可以将某些东西委派给现有机制。

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);

08-18 17:56