-
1. Re: How to remove additional wrappering from a nested object, for deserialization?
pnakaska Dec 24, 2014 2:49 PM (in response to pnakaska)The Geometry class from com.vividsolutions.jts:
(pom.xml)
<dependency>
<groupId>com.vividsolutions.jts</groupId>
<artifactId>jts-gwt</artifactId>
<version>1.14-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- and sources -->
<dependency>
<groupId>com.vividsolutions.jts</groupId>
<artifactId>jts-gwt</artifactId>
<version>1.14-SNAPSHOT</version>
<classifier>sources</classifier>
<scope>provided</scope>
</dependency>
in the Entrypoint, Jackson Marshalling is enabled:
RestClient.setJacksonMarshallingActive(true);
also in the POM, errai-jaxrs-provider has been removed (Jackson/Resteasy used server side)
This issue relates to com.vividsolutions.jts.Geometry and it's nested classes, which are all Serializeable.
The applicationn provides a search service which responds to queries with a Geometry, containing the coordinates (Polygon).
The GeometrySerializer
public class GeometrySerializer
{
public String serialize(Geometry value)
{
if (value instanceof Polygon)
{
return writePolygon((Polygon)value);
}
else
{
throw new UnsupportedOperationException("Unsupported Geometry type: " + value.getClass().getName());
}
}
private String writePolygon(Polygon value)
{
JSONObject obj = new JSONObject();
obj.put("type", new JSONString("Polygon"));
obj.put("coordinates", writePolygonCoordinates(value));
return obj.toString();
}
private JSONValue writePolygonCoordinates(Polygon value)
{
JSONArray array = new JSONArray();
array.set(0, writeLineStringCoords(value.getExteriorRing()));
for (int i = 0; i != value.getNumInteriorRing(); ++i)
{
array.set(i, writeLineStringCoords(value.getInteriorRingN(i)));
}
return array;
}
private JSONArray writeLineStringCoords(LineString ring)
{
JSONArray array = new JSONArray();
for (int i = 0; i != ring.getNumPoints(); ++i)
{
Point p = ring.getPointN(i);
array.set(i, writePointCoords(p));
}
return array;
}
private JSONArray writePointCoords(Point p)
{
JSONArray array = new JSONArray();
array.set(0, new JSONNumber(p.getX()));
array.set(1, new JSONNumber(p.getY()));
return array;
}
}
The result string of the serializer call writePolygonCoordinates (on the server, before sent to client) for the test case is:
{"type":"Polygon", "coordinates":[[[-117.76469603701167,57.692329503799144],[-117.76469603701167,55.14112833650245],[-121.58793822451068,55.14112833650245],[-121.58793822451068,57.692329503799144],[-117.76469603701167,57.692329503799144]]]}"
on the client in the deserializer:
public Geometry deserialize(EJValue o)
{
EJObject obj = o.isObject();
String typeName = obj.get("type").isString().stringValue();
if (typeName.equals("Polygon"))
{
EJValue ejValue = obj.get("coordinates");
return parsePolygonCoordinates(ejValue.isArray());
}
else
{
throw new UnsupportedOperationException("Unsupported geometry type: " + typeName);
}
}
private Polygon parsePolygonCoordinates(EJArray array)
{
return gf.createPolygon(
parseExteriorRing(array),
parseInteriorRings(array));
}
private LinearRing parseExteriorRing(EJArray array)
{
return gf.createLinearRing(parseLineString(array.get(0).isArray()));
}
private LinearRing[] parseInteriorRings(EJArray array)
{
LinearRing rings[] = new LinearRing[array.size() - 1];
for (int i = 1; i < array.size(); ++i)
{
rings[i - 1] = gf.createLinearRing(parseLineString(array.get(i).isArray()));
}
return rings;
}
private Coordinate[] parseLineString(EJArray array)
{
Coordinate[] points = new Coordinate[array.size()];
for (int i = 0; i != array.size(); ++i)
{
points[i] = parseCoordinate(array.get(i).isArray());
}
return points;
}
private Coordinate parseCoordinate(EJArray coords)
{
return new Coordinate(
coords.get(0).isNumber().doubleValue(),
coords.get(1).isNumber().doubleValue());
}
The deserializer (client) can retrieve the coordinates off of the document, but it looks like this:
{"^ObjectID":"10", "^Value":[{"^ObjectID":"11", "^Value":[{"^ObjectID":"12", "^Value":[{"^ObjectID":"13", "^NumVal":-117.76469603701167},{"^ObjectID":"14", "^NumVal":57.692329503799144}]},{"^ObjectID":"15", "^Value":[{"^ObjectID":"16", "^NumVal":-117.76469603701167},{"^ObjectID":"17", "^NumVal":55.14112833650245}]},{"^ObjectID":"18", "^Value":[{"^ObjectID":"19", "^NumVal":-121.58793822451068},{"^ObjectID":"20", "^NumVal":55.14112833650245}]},{"^ObjectID":"21", "^Value":[{"^ObjectID":"22", "^NumVal":-121.58793822451068},{"^ObjectID":"23", "^NumVal":57.692329503799144}]},{"^ObjectID":"24", "^Value":[{"^ObjectID":"25", "^NumVal":-117.76469603701167},{"^ObjectID":"26", "^NumVal":57.692329503799144}]}]}]}
The ejValue.isArray() returns null. it appears to be failing because it's got these additional tags?
-
2. Re: How to remove additional wrappering from a nested object, for deserialization?
csa Dec 30, 2014 11:10 AM (in response to pnakaska)Hi Phillip!
It appears you've created your own custom marshallers using @ClientMarshaller and @ServerMarshaller. Is this correct? If so, you do NOT want to activate Jackson marshalling (don't set RestClient.setJacksonMarshallingActive(true)) because then it's assumed that Errai's generated and built-in marshallers will take care of serialization/deserialization and the required ObjectIDs/NumVals etc. are added to the Jackson JSON.
So, setting RestClient.setJacksonMarshallingActive(false) or simply removing this line will cause the unmodified JSON (as emitted by your marshaller) to be used for demarshalling.
Cheers,
Christian