filosganga / geogson

GeoJSON support for Google gson library
Apache License 2.0
69 stars 28 forks source link

ClassCastException while handling MultiPolygons #15

Closed thorsten-k closed 10 years ago

thorsten-k commented 10 years ago

This minimal example demonstrates the parsing of a MultiPolygon:

Gson gsonGeometry = new GsonBuilder().registerTypeAdapterFactory(new GeometryAdapterFactory()).create();
String json = "{ \"type\": \"MultiPolygon\", \"coordinates\": [ [ [ [ 15.0, 20.0 ],[ 16.0, 21.0 ] ] ], [ [ [ 11.0, 24.4 ], [ 11.0, 18.6 ] ] ] ] }";
System.out.println(json);
MultiPolygon jMultiPolygon = gsonGeometry.fromJson(json,MultiPolygon.class);

The above code give the following exception:

Exception in thread "main" java.lang.ClassCastException: com.github.filosganga.geogson.model.positions.AreaPositions cannot be cast to com.github.filosganga.geogson.model.positions.MultiDimensionalPositions
    at com.github.filosganga.geogson.gson.GeometryAdapterFactory$GeometryAdapter$7.get(GeometryAdapterFactory.java:242)
    at com.github.filosganga.geogson.gson.GeometryAdapterFactory$GeometryAdapter$7.get(GeometryAdapterFactory.java:237)
    at com.github.filosganga.geogson.util.ChainableOptional.of(ChainableOptional.java:39)
    at com.github.filosganga.geogson.util.ChainableOptional.or(ChainableOptional.java:46)
    at com.github.filosganga.geogson.gson.GeometryAdapterFactory$GeometryAdapter.buildGeometry(GeometryAdapterFactory.java:130)
    at com.github.filosganga.geogson.gson.GeometryAdapterFactory$GeometryAdapter.read(GeometryAdapterFactory.java:113)
    at com.github.filosganga.geogson.gson.GeometryAdapterFactory$GeometryAdapter.read(GeometryAdapterFactory.java:60)
    at com.google.gson.Gson.fromJson(Gson.java:803)
    at com.google.gson.Gson.fromJson(Gson.java:768)
    at com.google.gson.Gson.fromJson(Gson.java:717)
    at com.google.gson.Gson.fromJson(Gson.java:689)
bkiselka commented 10 years ago

Due to the fact that the example is not a valid LinearRing as it is not closed, the following test does not work in JtsAdapterFactoryTest:

@Test
public void testBug15() {
    Gson gsonGeometry = new GsonBuilder().registerTypeAdapterFactory(new GeometryAdapterFactory()).registerTypeAdapterFactory(new JtsAdapterFactory()).create();
    String json = "{ \"type\": \"MultiPolygon\", \"coordinates\": [ [ [ [ 15.0, 20.0 ],[ 16.0, 21.0 ] ] ], [ [ [ 11.0, 24.4 ], [ 11.0, 18.6 ] ] ] ] }";
    System.out.println(json);
    MultiPolygon jMultiPolygon = gsonGeometry.fromJson(json, MultiPolygon.class);

    // now really check the result
    String parsedJson = this.toTest.toJson(jMultiPolygon, MultiPolygon.class);

    // as we can't compare the input JSON string due to blanks and ordering, so compare it with the generated string
    String expectedJson = "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[15.0,20.0],[16.0,21.0]]],[[[11.0,24.4],[11.0,18.6]]]]}"; //$NON-NLS-1$
    assertThat(parsedJson, equalTo(expectedJson));
}

To my surprise this did work in GeometryAdapterFactoryTest:

@Test
public void testBug15() {
Gson gsonGeometry = new GsonBuilder().registerTypeAdapterFactory(new GeometryAdapterFactory()).create();
String json = "{ \"type\": \"MultiPolygon\", \"coordinates\": [ [ [ [ 15.0, 20.0 ],[ 16.0, 21.0 ] ] ], [ [ [ 11.0, 24.4 ], [ 11.0, 18.6 ] ] ] ] }";
MultiPolygon jMultiPolygon = gsonGeometry.fromJson(json, MultiPolygon.class);

// now really check the result
String parsedJson = this.toTest.toJson(jMultiPolygon, MultiPolygon.class);

// as we can't compare the input JSON string due to blanks and ordering, so compare it with the generated string
String expectedJson = "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[15.0,20.0],[16.0,21.0]]],[[[11.0,24.4],[11.0,18.6]]]]}"; //$NON-NLS-1$
assertThat(parsedJson, equalTo(expectedJson));
}

Obviously in geogson-core the MultiPolygon is created by positions and thus the inner Polygon is not checked.