how can I map the subsequent XML file to the right inheriting class. The problem is, that I have four different API methods, this is a response of one of the methods named "api_search_location"
<?xml version="1.0" encoding="UTF-8"?>
<ft>
<response>
<client device="" appName="" clientId="123" appVersion=""/>
<responseType>api_search_location</responseType>
<responseTime>2013-01-21 11:55:43</responseTime>
<locations status="list">
<location name="60201040" title="Praterstern" municipality="Wien" type="stop" listIndex="0:1" coordName="wgs84" wgs84Lat="48.21815" wgs84Lon="16.39176" coordX="" coordY="" distanceMeter="" durationMinutes=""/>
<location name="60201848" title="Praterstern/Lassallestraße" municipality="Wien" type="stop" listIndex="1:2" coordName="wgs84" wgs84Lat="48.21962" wgs84Lon="16.39382" coordX="" coordY="" distanceMeter="" durationMinutes=""/>
</locations>
<message messageCode="1">ok</message>
</response>
</ft>
I have the following class "FtResponse" for all the four response types:
package model.response;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
@Root(name="ft")
public class FtResponse {
@Element
private Response response;
public FtResponse() {
super();
}
public FtResponse(Response response) {
super();
this.response = response;
}
public Response getResponse() {
return response;
}
public void setResponse(Response response) {
this.response = response;
}
@Override
public String toString() {
return "FtResponse [response=" + response + "]";
}
}
And I have the class "Response". All the specific response classes inherit from this general class:
package model.response;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
@Root(name = "request")
public class Response {
@Element
private Client client;
@Element
private String responseType;
@Element
private String responseTime;
public Response() {
super();
}
public Response(Client client, String responseType, String responseTime) {
super();
this.client = client;
this.responseType = responseType;
this.responseTime = responseTime;
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
public String getResponseType() {
return responseType;
}
public void setResponseType(String responseType) {
this.responseType = responseType;
}
public String getResponseTime() {
return responseTime;
}
public void setResponseTime(String responseTime) {
this.responseTime = responseTime;
}
@Override
public String toString() {
return "Response [client=" + client + ", responseType=" + responseType
+ ", responseTime=" + responseTime + "]";
}
}
This is one of my specific response classes:
package model.response;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
@Root(name = "response")
public class SearchLocationStopsNearbyResponse extends Response {
@Element
private Client client;
@Element
private String responseType;
@Element
private String responseTime;
@Element
private LocationCentre locationCentre;
@Element
private Locations locations;
@Element
private Message message;
public SearchLocationStopsNearbyResponse() {
super();
}
public SearchLocationStopsNearbyResponse(Client client,
String responseType, String responseTime,
LocationCentre locationCentre, Locations locations, Message message) {
super();
this.client = client;
this.responseType = responseType;
this.responseTime = responseTime;
this.locationCentre = locationCentre;
this.locations = locations;
this.message = message;
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
public String getResponseType() {
return responseType;
}
public void setResponseType(String responseType) {
this.responseType = responseType;
}
public String getResponseTime() {
return responseTime;
}
public void setResponseTime(String responseTime) {
this.responseTime = responseTime;
}
public LocationCentre getLocationCentre() {
return locationCentre;
}
public void setLocationCentre(LocationCentre locationCentre) {
this.locationCentre = locationCentre;
}
public Locations getLocations() {
return locations;
}
public void setLocations(Locations locations) {
this.locations = locations;
}
public Message getMessage() {
return message;
}
public void setMessage(Message message) {
this.message = message;
}
@Override
public String toString() {
return "SearchLocationStopsNearbyResponse [client=" + client
+ ", responseType=" + responseType + ", responseTime="
+ responseTime + ", locationCentre=" + locationCentre
+ ", locations=" + locations + ", message=" + message + "]";
}
}
My problem is, that when i try to read in all the data to my nested classes i get the following exception:
org.simpleframework.xml.core.ElementException: Element 'locationCentre' does not have a match in class model.response.Response at line 7
at org.simpleframework.xml.core.Composite.readElement(Composite.java:527)
at org.simpleframework.xml.core.Composite.readElements(Composite.java:445)
at org.simpleframework.xml.core.Composite.access$400(Composite.java:59)
at org.simpleframework.xml.core.Composite$Builder.read(Composite.java:1383)
at org.simpleframework.xml.core.Composite.read(Composite.java:201)
at org.simpleframework.xml.core.Composite.read(Composite.java:148)
at org.simpleframework.xml.core.Composite.readVariable(Composite.java:623)
at org.simpleframework.xml.core.Composite.readInstance(Composite.java:573)
at org.simpleframework.xml.core.Composite.readUnion(Composite.java:549)
at org.simpleframework.xml.core.Composite.readElement(Composite.java:532)
at org.simpleframework.xml.core.Composite.readElements(Composite.java:445)
at org.simpleframework.xml.core.Composite.access$400(Composite.java:59)
at org.simpleframework.xml.core.Composite$Builder.read(Composite.java:1383)
at org.simpleframework.xml.core.Composite.read(Composite.java:201)
at org.simpleframework.xml.core.Composite.read(Composite.java:148)
at org.simpleframework.xml.core.Traverser.read(Traverser.java:92)
at org.simpleframework.xml.core.Persister.read(Persister.java:625)
at org.simpleframework.xml.core.Persister.read(Persister.java:606)
at org.simpleframework.xml.core.Persister.read(Persister.java:584)
at org.simpleframework.xml.core.Persister.read(Persister.java:543)
at org.simpleframework.xml.core.Persister.read(Persister.java:521)
at org.simpleframework.xml.core.Persister.read(Persister.java:426)
at TestRead.main(TestRead.java:19)
I unterstood that Simple tries to find the element "locationCentre" in the class "Response", but there is no appropriate element. But how can I say to Simple, that it should choose the correct specific class, in this case "SearchLocationStopsNearbyResponse" depending on the XML response file?
If i understand aright, you use <responseType>...</responseType>
to decide which implementation of Response
is the correct one. I guess there's no such functionality in Simple.
Possibly unions can help you here.
However - you can customize the process of serialization / deserialisation by using a Converter
or Visitor
. This may not as easy as some annotations but should be capable of solving your problem.
So here is what you have to do if you use a Converter
:
ResponseConverter
which implements the Converter
-Interface (if you dont need it you can leave the write()
-method)Response
-class (and the classes wich extend it?) with @Convert
annotation (eg. @Convert(ResponseConverter)
) so simple knows that you want to use your own.AnnotationStrategy
to your Serializer
(eg. Serializer ser = new Persister(new AnnotationStrategy());
)See also: