Cannot parse response with JAXB - java

I am trying to send a REST request and parse the response, but it returns NullPointerException. I assume the issue is with namespace.
When I have package-info.java file, it returns NullPointerException and when I do not it returns following:
Exception in thread "main"
org.springframework.http.converter.HttpMessageNotReadableException:
Could not unmarshal to [class com.expedia.HotelListResponse]: unexpected
element (uri:"http://v3.hotel.wsapi.ean.com/", local:"HotelListResponse").
Expected elements are <{}ChargeableRateInfo>,<{}HotelList>,
<{}HotelListResponse>,<{}HotelSummary>,<{}NightlyRate>,
<{}NightlyRatesPerRoom>,<{}RateInfo>,<{}RoomRateDetails>,
<{}RoomRateDetailsList>,<{}Surcharge>,<{}Surcharges>,<{}ValueAdd>,
<{}ValueAdds>; nested exception is javax.xml.bind.UnmarshalException:
unexpected element (uri:"http://v3.hotel.wsapi.ean.com/",
local:"HotelListResponse"). Expected elements are <{}ChargeableRateInfo>,
<{}HotelList>,<{}HotelListResponse>,<{}HotelSummary>,<{}NightlyRate>,
<{}NightlyRatesPerRoom>,<{}RateInfo>,<{}RoomRateDetails>,
<{}RoomRateDetailsList>,<{}Surcharge>,<{}Surcharges>,<{}ValueAdd>,
<{}ValueAdds>
If I remove qualified part of package-info the code shows following:
>>>0ABD9-732-A12-124-2BE4FD21A
>>>1
nullPointerException
....
Sample partial response
<ns2:HotelListResponse>
<customerSessionId>0ABD9-732-A12-124-2BE4FD21A
</customerSessionId>
<numberOfRoomsRequested>1</numberOfRoomsRequested>
<moreResultsAvailable>true</moreResultsAvailable>
<cacheKey>168951a:159922be3fd:-11ce</cacheKey>
<cacheLocation>19.11.13.19:7300</cacheLocation>
<HotelList size="20" activePropertyCount="1231">
<HotelSummary order="0">
<hotelId>335698</hotelId>
<name>Park Plaza Westminster Bridge London</name>
<address1>200 Westminster Bridge Road</address1>
<city>London</city>
<postalCode>SE1 7UT</postalCode>
<countryCode>GB</countryCode>
<airportCode>LCY</airportCode>
<supplierType>E</supplierType>
<propertyCategory>1</propertyCategory>
<hotelRating>4.0</hotelRating>
<confidenceRating>45</confidenceRating>
<amenityMask>1511947</amenityMask>
<locationDescription>Near London Aquarium</locationDescription>
<shortDescription><p><b>Property Location</b>
<br />A stay at Park Plaza Westminster Bridge London places
you in the heart of London, steps from London Aquarium and London
Dungeon. This 4-star hotel is close to</shortDescription>
<highRate>314.27</highRate>
<lowRate>254.35</lowRate>
<rateCurrencyCode>USD</rateCurrencyCode>
<latitude>51.50111</latitude>
<longitude>-0.11733</longitude>
<proximityDistance>0.7890795</proximityDistance>
<proximityUnit>MI</proximityUnit>
<hotelInDestination>true</hotelInDestination>
<thumbNailUrl>/hotels/4000000/3120000/3113100/3113039/3113039_31_t.jpg
</thumbNailUrl>
<deepLink>http://www.travelnow.com/templates/441384/hotels/335698/overview?lang=en&currency=USD&standardCheckin=11/23/2016&standardCheckout=11/25/2016&roomsCount=1&rooms[0].adultsCount=1
</deepLink>
<RoomRateDetailsList>
<RoomRateDetails>
<roomTypeCode>200750627</roomTypeCode>
<rateCode>203729567</rateCode>
<maxRoomOccupancy>2</maxRoomOccupancy>
<quotedRoomOccupancy>1</quotedRoomOccupancy>
<minGuestAge>0</minGuestAge>
<roomDescription>Superior Twin Room, 2 Single Beds
</roomDescription>
<promoId>209171300</promoId>
<promoDescription>Save 15%</promoDescription>
<currentAllotment>9</currentAllotment>
<propertyAvailable>true</propertyAvailable>
<propertyRestricted>false</propertyRestricted>
<expediaPropertyId>3113039</expediaPropertyId>
<rateKey>81300a5d-b697-457e-a059-2c22f6ce389b</rateKey>
<RateInfo priceBreakdown="true" promo="true" rateChange="true">
<ChargeableRateInfo averageBaseRate="263.30"
averageRate="217.28" commissionableUsdTotal="521.48"
currencyCode="USD" maxNightlyRate="222.61" nightlyRateTotal="434.57"
surchargeTotal="86.91" total="521.48">
<NightlyRatesPerRoom size="2">
<NightlyRate baseRate="269.75" rate="222.61" promo="true" />
<NightlyRate baseRate="256.84" rate="211.96" promo="true" />
</NightlyRatesPerRoom>
<Surcharges size="1">
<Surcharge type="TaxAndServiceFee" amount="86.91" />
</Surcharges>
</ChargeableRateInfo>
</RateInfo>
<ValueAdds size="1">
<ValueAdd id="2048">
<description>Free Wireless Internet</description>
</ValueAdd>
</ValueAdds>
</RoomRateDetails>
</RoomRateDetailsList>
</HotelSummary>
<HotelSummary order="1">
Request
final String URL = "http://api.ean.com/ean-services/rs/hotel/v3/list?cid="+CID+ "&apikey=" +API_KEY +"&sig= " + sig + "&apiExperience=PARTNER_WEBSITE&arrivalDate=12/11/2016&departureDate=12/18/2016&room1=1&city=London&stateProvinceCode=LN&countryCode=UK";
System.err.println("URL:" + URL);
RestTemplate restTemplate = new RestTemplate();
HotelListResponse hotelResponse = restTemplate.getForObject(URL,HotelListResponse.class);
System.err.println(">>>" + hotelResponse.getCacheKey());
System.err.println(">>>" + hotelResponse.getNumberOfRoomsRequested());
System.err.println(" Hotel Summaries Size>>>" + hotelResponse.getHotelList().getHotelSummaries().size());
package-info.java
#XmlSchema(
namespace = "http://v3.hotel.wsapi.ean.com/",
elementFormDefault = XmlNsForm.QUALIFIED)
package com.expedia;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
HotelListResponse
#XmlRootElement(name = "HotelListResponse")
#XmlAccessorType(XmlAccessType.FIELD)
public class HotelListResponse {
#XmlElement(name = "customerSessionId")
private String customerSessionId;
#XmlElement(name = "numberOfRoomsRequested")
private short numberOfRoomsRequested;
#XmlElement(name = "moreResultsAvailable")
private boolean moreResultsAvailable;
#XmlElement(name = "cacheKey")
private String cacheKey;
#XmlElement(name = "cacheLocation")
private String cacheLocation;
#XmlElement(name = "hotelList")
private HotelList hotelList;
getters and setters go here
HotelList
#XmlRootElement(name="HotelList")
#XmlAccessorType(XmlAccessType.FIELD)
public class HotelList {
#XmlAttribute(name="size")
private int size;
#XmlAttribute(name="activePropertyCount")
private int activePropertyCount;
private List<HotelSummary> hotelSummaries;
getters and setters go here
HotelSummary
#XmlRootElement(name="HotelSummary")
#XmlAccessorType(XmlAccessType.FIELD)
public class HotelSummary {
#XmlAttribute(name="order")
private int order;
#XmlElement(name="hotelId")
private int hotelId;
#XmlElement(name="name")
private String name;
#XmlElement(name="address1")
private String address1;
#XmlElement(name="city")
private String city;
#XmlElement(name="stateProvinceCode")
private String stateProvinceCode;
#XmlElement(name="postalCode")
private int postalCode;
#XmlElement(name="countryCode")
private String countryCode;
#XmlElement(name="airportCode")
private String airportCode;
#XmlElement(name="supplierType")
private String supplierType;
#XmlElement(name="propertyCategory")
private int propertyCategory;
#XmlElement(name="hotelRating")
private float hotelRating;
#XmlElement(name="confidenceRating")
private int confidenceRating;
#XmlElement(name="amenityMask")
private int amenityMask;
#XmlElement(name="locationDescription")
private String locationDescription;
#XmlElement(name="shortDescription")
private String shortDescription;
#XmlElement(name="highRate")
private double highRate;
#XmlElement(name="lowRate")
private double lowRate;
#XmlElement(name="rateCurrencyCode")
private String rateCurrencyCode;
#XmlElement(name="latitude")
private double latitude;
#XmlElement(name="longitude")
private double longitude;
#XmlElement(name="proximityDistance")
private double proximityDistance;
#XmlElement(name="proximityUnit")
private String proximityUnit;
#XmlElement(name="hotelInDestination")
private boolean hotelInDestination;
#XmlElement(name="thumbNailUrl")
private String thumbNailUrl;
#XmlElement(name="deepLink")
private String deepLink;
#XmlElement(name="RoomRateDetailsList")
private RoomRateDetailsList roomRateDetailsList;
getters and setters go here
RoomRateDetailsList
#XmlRootElement(name = "RoomRateDetailsList")
#XmlAccessorType(XmlAccessType.FIELD)
public class RoomRateDetailsList {
#XmlElement(name = "RoomRateDetails")
private RoomRateDetails roomRateDetails;
getters and setters go here
RoomRateDetails
#XmlRootElement(name = "RoomRateDetails")
#XmlAccessorType(XmlAccessType.FIELD)
public class RoomRateDetails {
#XmlElement(name = "roomTypeCode")
private int roomTypeCode;
#XmlElement(name = "rateCode")
private int rateCode;
#XmlElement(name = "maxRoomOccupancy")
private int maxRoomOccupancy;
#XmlElement(name = "quotedRoomOccupancy")
private int quotedRoomOccupancy;
#XmlElement(name = "minGuestAge")
private int minGuestAge;
#XmlElement(name = "roomDescription")
private String roomDescription;
#XmlElement(name = "currentAllotment")
private int currentAllotment;
#XmlElement(name = "propertyAvailable")
private boolean propertyAvailable;
#XmlElement(name = "propertyRestricted")
private boolean propertyRestricted;
#XmlElement(name = "expediaPropertyId")
private int expediaPropertyId;
#XmlElement(name = "rateKey")
private String rateKey;
#XmlElement(name="RateInfo")
private RateInfo rateInfo;
#XmlElement(name="ValueAdds")
private ValueAdds valueAdds;
getters and setters go here
RateInfo
#XmlRootElement(name="RateInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class RateInfo {
#XmlAttribute(name="priceBreakdown")
private boolean priceBreakdown;
#XmlAttribute(name="promo")
private boolean promo;
#XmlAttribute(name="rateChange")
private boolean rateChange;
#XmlElement(name="ChargeableRateInfo")
private ChargeableRateInfo chargeableRateInfo;
getters and setters go here
ChargeableRateInfo
#XmlRootElement(name = "ChargeableRateInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class ChargeableRateInfo {
#XmlAttribute(name = "averageBaseRate")
private double averageBaseRate;
#XmlAttribute(name = "averageRate")
private double averageRate;
#XmlAttribute(name = "commissionableUsdTotal")
private double commissionableUsdTotal;
#XmlAttribute(name = "currencyCode")
private String currencyCode;
#XmlAttribute(name = "maxNightlyRate")
private double maxNightlyRate;
#XmlAttribute(name = "nightlyRateTotal")
private double nightlyRateTotal;
#XmlAttribute(name = "surchargeTotal")
private double surchargeTotal;
#XmlAttribute(name = "total")
private double total;
#XmlElement(name = "NightlyRatesPerRoom")
private NightlyRatesPerRoom nightlyRatesPerRoom;
#XmlElement(name = "Surcharges")
private Surcharges surcharges;
getters and setters go here
NightlyRatesPerRoom
#XmlRootElement(name = "NightlyRatesPerRoom")
#XmlAccessorType(XmlAccessType.FIELD)
public class NightlyRatesPerRoom {
#XmlAttribute(name = "size")
private int size;
#XmlElement(name = "NightlyRate")
private List<NightlyRate> nightlyRates;
getters and setters go here
NightlyRate
#XmlRootElement(name = "NightlyRate")
#XmlAccessorType(XmlAccessType.FIELD)
public class NightlyRate {
#XmlAttribute(name = "baseRate")
private double baseRate;
#XmlAttribute(name = "rate")
private double rate;
#XmlAttribute(name = "promo")
private boolean promo;
getters and setters go here
Surcharges
#XmlRootElement(name = "Surcharges")
#XmlAccessorType(XmlAccessType.FIELD)
public class Surcharges {
#XmlAttribute(name = "size")
private int size;
#XmlElement(name = "Surcharge")
private List<Surcharge> surcharges;
getters and setters go here
Surcharge
#XmlRootElement(name = "Surcharge")
#XmlAccessorType(XmlAccessType.FIELD)
public class Surcharge {
#XmlAttribute(name = "type")
private String type;
#XmlAttribute(name = "amount")
private double amount;
getters and setters go here
ValueAdds
#XmlRootElement(name = "ValueAdds")
#XmlAccessorType(XmlAccessType.FIELD)
public class ValueAdds {
#XmlElement(name = "size")
private int size;
#XmlElement(name = "ValueAdd")
private ValueAdd valueAdd;
getters and setters go here
ValueAdd
#XmlRootElement(name = "ValueAdd")
#XmlAccessorType(XmlAccessType.FIELD)
public class ValueAdd {
#XmlElement(name = "description")
private String description;
getters and setters go here

Your schema declares elementFormDefault="qualified" as we can see in your package-info, so you must remove the ns2 prefix at the root Element, or you must add it to all the inner elements, depends on the xmlns declaration (that we can't see).

Related

Cannot parse XML using Jackson, model never gets populated

I am trying to parse bellow xml using Jackson library but with no luck. I tried few things with my model, and I don't see the problem...
XML:
<?xml version="1.0" encoding="UTF-8"?>
<litre version="1.1" creator="Dummy Creator"
xsi:schemaLocation="http://www.dummy.com/xmlschemas/DummyExtension.xsd>
<metadata>
<link href="dummy.com">
<text>Dummy</text>
</link>
<time>2012-10-24T23:22:51.000Z</time>
</metadata>
<krt>
<name>Untitled</name>
<geskrt>
<pkrt data1="123" data2="321">
<ints>100</ints>
<time>2012-10-24T22:21:15.000Z</time>
<extensions>
<axtpx:DummyExtension>
<xtpx:hor>40000</xtpx:hor>
</axtpx:DummyExtension>
</extensions>
</pkrt>
<pkrt data1="543" data2="345">
<ints>100</ints>
<time>2012-10-24T23:29:40.000Z</time>
<extensions>
<axtpx:DummyExtension>
<xtpx:hor>50000</xtpx:hor>
</axtpx:DummyExtension>
</extensions>
</pkrt>
</geskrt>
</krt>
</litre>
POJO:
#JacksonXmlRootElement(localName = "litre")
public #Data class Model {
#JacksonXmlProperty(localName = "pkrt")
#JacksonXmlElementWrapper(useWrapping = false)
private List<Data> entries;
public static #Data class Data {
#JacksonXmlProperty(isAttribute = true, localName = "data1")
private double dataOne;
#JacksonXmlProperty(isAttribute = true, localName = "data2")
private double dataTwo;
#JacksonXmlProperty(localName = "ints")
private double inters;
private String time;
#JacksonXmlProperty(namespace = "xtpx:hor")
private long hours;
}
}
While trying to deserialize with:
Model model = mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.readValue(filePath.toFile(), Model.class);
parsing always passes with no exception, but entries list is always empty...
I would appreciate any help, thanx!
You most certainly have to do something like this:
#JacksonXmlRootElement(localName = "litre")
public #Data class Litre {
#JacksonXmlProperty(localName = "krt")
private Krt krt;
public static #Data class Krt {
#JacksonXmlProperty(localName = "geskrt")
private Geskrt geskrt;
}
public static #Data class Geskrt {
#JacksonXmlProperty(localName = "pkrt")
#JacksonXmlElementWrapper(useWrapping = false)
private List<Pkrt> pkrt;
}
public static #Data class Pkrt {
#JacksonXmlProperty(isAttribute = true, localName = "data1")
private double dataOne;
#JacksonXmlProperty(isAttribute = true, localName = "data2")
private double dataTwo;
#JacksonXmlProperty(localName = "ints")
private double inters;
private String time;
#JacksonXmlProperty(namespace = "xtpx:hor")
private long hours;
}
}

findAll UUID MongoRepository

I'm trying to achive a findAllByUUID using mongo-spring-boot, but with no luck.
What I have:
public interface CarMatchRepository extends MongoRepository<CarMatchEntity, String> {
List<CarMatchEntity> findAllByCarID(Iterable<UUID> ids);
CarMatchEntity findByCarID(UUID carID);
}
Function call:
public void addCarsToCollection(String id, List<UUID> carId) {
List<CarMatchEntity> entities = carMatchRepository.findAllByCarID(carId); <--- empty
}
If I call findByCarID() it retrieves correctly a single object (if exists) but using Iterable the query does not fail, but it never returns any object. Am I doing something wrong here or am I taking the wrong road for this problem?
Thanks!
Edit:
#Document(collection = "car_index")
public class CarMatchEntity implements Serializable {
#Id
private String id;
private UUID carID;
//partner data
private UUID partnerID;
private String partnerThumbURL;
private String partnerName;
private Date partnerMembershipSince;
// car location
private List<Double> location;
private String district;
private String city;
// car data
private CarType carType;
private String carBrand;
private String carModel;
private String carPlate;
private List<CarFeature> carFeatures;
private String carAddress;
private String description;
private BigDecimal hourFare;
private BigDecimal dayFare;
private BigDecimal weekFare;
private BigDecimal dailyPrice;
private BigDecimal suggestedHourlyPrice;
private BigDecimal suggestedDailyPrice;
private BigDecimal suggestedWeeklyPrice;
private String carThumbURL;
private Map<String, CarPhotos> carPhotosURL;
private CarAvailability availability;
private CarStatus carStatus;
private String carYear;
private FuelType fuelType;
#Transient
private DayOfWeek prohibitedDay;
private String carYearModel;
#Transient
private double partnerRating = 5.0;
private CarTransmission carTransmission;
private CarColor carColor;
private String odometer;
private Integer manufactureYear;
private String fipeCode;
private String renavam;
private String chassi;
private InsuranceCompany insuranceCompany;
private List<CarSpecialFeature> carSpecialFeatures;
private BigDecimal deductible;
private Boolean superCar;
public CarMatchEntity() {
}
Try using JSON based queries with SpEL expressions
#Query("{carID: { $in: ?0 } })")
List<CarMatchEntity> findAllByCarIds(List<UUID> ids);
Use
List<CarMatchEntity> findAllByCarIDIn(Iterable<UUID> ids);
instead of
List<CarMatchEntity> findAllByCarID(Iterable<UUID> ids);
UPDATE:
Did you try to explicitly declare JPQL query instead of relying on Spring Data query generation mechanism?
#Query("select e from CarMatchEntity e where e.carID in (:ids)")
List<CarMatchEntity> findAllByCarID(#Param("ids") Iterable<UUID> ids);
UPDATE 2:
Another solution I would try is to declare argument ids in findAllByCarIDIn method as Collection<UUID> instead of Iterable<UUID>.

How to collect all xml elements in a list?

I am using jackson-dataformat-xml.
I have the following classes:
public class CTHotel {
#JacksonXmlProperty(localName = "basic-info")
private HotelBaseInfo hotelBaseInfo;
//other properties and getters and setters
}
public class HotelBaseInfo {
#JacksonXmlProperty(localName = "hotel-name")
private String hotelName;
#JacksonXmlElementWrapper(localName = "hotel-amenities")
private List<HotelAmenity> hotelAmenities;
//other properties and getters/setters
}
public class HotelAmenity {
private String category;
private String description;
#JacksonXmlElementWrapper(localName = "amenities")
private List<String> amenities;
//other properties and getters/setters
}
My XML is this:
<hotels>
<hotel>
<basic-info>
<hotel-name>Hotel XYZ</hotel-name>
<hotel-amenities>
<hotel-amenity>
<category>F&B</category>
<description>Random Text</description>
<amenities>
<amenity>Cafe</amenity>
<amenity>Bar</amenity>
<amenity>Rastaurant</amenity>
</amenities>
</hotel-amenity>
<hotel-amenity>
...
</hotel-amenity>
</hotel-amenities>
</basic-info>
</hotel>
<hotel>
...
</hotel>
</hotels>
My question is, how can I map amenities as list of strings in my HotelAmenity class as mentioned above ? What annotation should I use on amenities field ?
#JacksonXmlElementWrapper annotation on hotelAmenities field of Hotel class is working just fine.
I get the below error while mapping :
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
at [Source: java.io.StringReader#507bcc81; line: 3, column: 1039] (through reference chain: com.example.response.HotelSearchResponse["hotels"]->java.util.ArrayList[2]->com.example.response.CTHotel["basic-info"]->com.example.response.HotelBaseInfo["hotel-amenities"]->java.util.ArrayList[1]->com.example.response.HotelAmenity["amenities"]->java.util.ArrayList[9])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148) ~[jackson-databind-2.6.5.jar:2.6.5]
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:857) ~[jackson-databind-2.6.5.jar:2.6.5]
...
Here's the code, that I hope would answer your question:
/**Class Hotels*/
#JacksonXmlRootElement(localName = "hotels")
public class Hotels {
#JacksonXmlElementWrapper(useWrapping = false)
private List<Hotel> hotel;
//Other getters and setters
}
/**Class Hotel*/
#JacksonXmlRootElement(localName = "hotel")
public class Hotel {
#JacksonXmlProperty(localName = "basic-info")
private HotelBaseInfo hotelBaseInfo;
//Other getters and setters
}
/**Class HotelBaseInfo*/
public class HotelBaseInfo {
#JacksonXmlProperty(localName = "hotel-name")
private String hotelName;
#JacksonXmlElementWrapper(localName = "hotel-amenities")
private List<HotelAmenity> hotelAmenities;
//Other getters and setters
}
/**Class HotelAmenity*/
public class HotelAmenity {
private String category;
private String description;
#JacksonXmlElementWrapper(localName = "amenities")
private List<Amenities> amenity;
static class Amenities {
#JacksonXmlText
private String value;
}
//Other getters and setters
}
Here's what worked for me:
public class JacksonXmlParsing {
#JacksonXmlRootElement(localName = "hotels")
static class HotelSearchResponse {
#JacksonXmlElementWrapper(localName = "hotel")
private List<CTHotel> hotels;
//other properties and getters and setters
}
static class CTHotel {
#JacksonXmlProperty(localName = "hotel-name")
private String hotelName;
#JacksonXmlElementWrapper(localName = "hotel-amenities")
private List<HotelAmenity> hotelAmenities;
//other properties and getters and setters
}
static class HotelAmenity {
private String category;
private String description;
#JacksonXmlElementWrapper
private List<String> amenities;
//other properties and getters/setters
}
public static void main(String[] args) throws IOException {
XmlMapper xmlMapper = new XmlMapper();
File file = new File("./src/main/resources/file.xml");
HotelSearchResponse response = xmlMapper.readValue(file, HotelSearchResponse.class);
System.out.println(response);
}
}
Output:
HotelSearchResponse(hotels=[CTHotel(hotelName=Hotel XYZ, hotelAmenities=[HotelAmenity(category=F&B, description=Random Text, amenities=[Cafe, Bar, Rastaurant])])])
But basic-info tag is missed, I could find out why.

SimpleXMLConverter parse xml nodes

I'm stuck. How to parse Node with same name child node?
In this example i need nodes with rate attribute.
<xml>
<Rates>
<Rates winrate_cap="9999">
<Rates rate="323"/>
<Rates rate="343"/>
<Rates rate="2338"/>
<Rates rate="233"/>
</Rates>
</Rates>
</xml>
My response wrapper class:
#Root(name = "xml", strict = false)
public class XMLResponse {
#ElementList(entry = "Rates")
public List<Rates> response;
public static class Rates {
#Attribute(name = "winrate_cap", required = false)
public String winrate_cup;
#ElementList(required = false, entry = "Rates")
public List<Rates> rates;
}
public static class Rates {
#Attribute(name = "rate", required = false)
public String rate;
}
}
You are on the right way. As you have many Rates here, better name the class more with more context and set the xml name via Annotation.
I've separated the XMLResponse and Rates classes, but this doesn't make any difference.
The class XMLRespone maps the <xml>...</xml> part:
#Root(name = "xml")
public class XMLRespone
{
#Element(name = "Rates")
private Rates rates;
// ...
}
All types for <Rates...>...</Rates> is done by Rates class (and it's inner classes, which map the structure:
#Root(name = "Rates")
public class Rates
{
#Element(name = "Rates")
private RateList rates;
// ...
public static class RateList
{
#ElementList(entry = "Rates", inline = true)
private ArrayList<RateValue> values;
#Attribute(name = "winrate_cap", required = true)
private int winrateCap;
// ...
}
public static class RateValue
{
#Attribute(name = "rate", required = true)
private int rate;
// ...
}
}
Deserializing your XML gives this output (using generated toString()):
XMLRespone{rates=Rates{rates=RateList{values=[RateValue{rate=323}, RateValue{rate=343}, RateValue{rate=2338}, RateValue{rate=233}], winrateCap=9999}}}

Can not unmarshall a (XML with namespace) inputstream into object

When I send a request to web service the following response will be received. I am using the following code to unmarshall the response XML to an object, but it seems nothing will be put into the object.
Server's response
<?xml version="1.0" encoding="utf-8"?>
<AvailabilityResponse DateTime="2014-02-18 08:32:04" DurationSecs="1.32" xmlns="example.com">
<Success></Success>
<Results ResultCount="9">
<Result>
<Outbound>
<FlightSegment>
<Departure>
<Airport CodeContext="IATA">DUS</Airport>
<DateTime>2014-12-10T09:55:00</DateTime>
</Departure>
<Arrival>
<Airport CodeContext="IATA">ZRH</Airport>
<DateTime>2014-12-10T11:10:00</DateTime>
</Arrival>
<FlightNumber CodeContext="IATA">LX1017</FlightNumber>
</FlightSegment>
</Outbound>
<Inbound>
<FlightSegment>
<Departure>
<Airport CodeContext="IATA">ZRH</Airport>
<DateTime>2014-12-15T07:25:00</DateTime>
</Departure>
<Arrival>
<Airport CodeContext="IATA">DUS</Airport>
<DateTime>2014-12-15T08:50:00</DateTime>
</Arrival>
<FlightNumber CodeContext="IATA">LX1016</FlightNumber>
</FlightSegment>
</Inbound>
<FareInfos CurrencyCode="EUR">
<FareReference>Y,Y</FareReference>
<BaseAmount>30</BaseAmount>
<TaxAmount>58</TaxAmount>
<TotalFare>126</TotalFare>
</FareInfos>
<Url>http://myexample.com</Url>
</Result>
<Result>....</Result>
<Result>....</Result>
<Result>....</Result>
<Result>....</Result>
<Result>....</Result>
<Result>....</Result>
<Result>....</Result>
<Result>....</Result>
</Results>
</AvailabilityResponse>
Code
String queryString = "http://example.com";
try {
URL page = new URL(queryString);
HttpURLConnection conn = (HttpURLConnection) page.openConnection();
conn.connect();
System.err.println("Results ");
this.results = (AvailabilityResponse) JAXB.unmarshal(conn.getInputStream(),
AvailabilityResponse.class);
System.err.println("Output:" + this.results.getResults().getResult().size());
Result in console (as there are 9 results in the Results tag, this number should be 9
Results
Output:0
AvailabilityResponse
#XmlRootElement(name = "AvailabilityResponse")
#XmlAccessorType(XmlAccessType.FIELD)
public class AvailabilityResponse {
#XmlElement(name = "Results")
private Results results = null;
#XmlElement (name = "Success")
private String success;
public AvailabilityResponse() {
this.results = new Results();
}
getters & setters go here
}
Results
#XmlRootElement(name = "Results")
#XmlAccessorType(XmlAccessType.FIELD)
public class Results {
#XmlElement(name = "Result")
private List<Result> result = null;
public Results() {
this.result = new ArrayList();
}
getters & setters go here
}
Result
#XmlRootElement(name = "Result")
#XmlAccessorType(XmlAccessType.FIELD)
public class Result {
#XmlElement(name = "Outbound")
private Outbound outbound = null;
#XmlElement(name = "Inbound")
private Inbound inbound = null;
#XmlElement(name = "FareInfos")
private FareInfos fareInfos = null;
#XmlElement (name = "Url")
private String Url;
public Result() {
this.outbound = new Outbound();
this.inbound = new Inbound();
this.fareInfos = new FareInfos();
}
getters & setters go here
}
OutBound
#XmlRootElement(name = "Outbound")
#XmlAccessorType(XmlAccessType.FIELD)
public class Outbound {
#XmlElement(name = "FlightSegment")
private FlightSegment flightSegment = null;
public Outbound() {
this.flightSegment = new FlightSegment();
}
getter & setter go here
}
InBound
#XmlRootElement(name = "Inbound")
#XmlAccessorType(XmlAccessType.FIELD)
public class Inbound {
#XmlElement(name = "FlightSegment")
private FlightSegment flightSegment = null;
public Inbound() {
this.flightSegment = new FlightSegment();
}
getter & setter go here
}
FlightSegment
#XmlRootElement(name = "FlightSegment")
#XmlAccessorType(XmlAccessType.FIELD)
public class FlightSegment {
#XmlElement(name = "Departure")
private Departure departure = null;
#XmlElement(name = "Arrival")
private Arrival arrival = null;
#XmlElement(name = "FlightNumber")
private String flightNumber;
public FlightSegment() {
this.departure = new Departure();
this.arrival = new Arrival();
}
getters & setters go here
}
Departure
#XmlRootElement (name = "Departure")
#XmlAccessorType (XmlAccessType.FIELD)
public class Departure {
#XmlElement (name = "Airport")
private String Airport;
#XmlElement (name = "DateTime")
private String DateTime;
getters & setters go here
}
Arrival
#XmlRootElement(name = "Arrival")
#XmlAccessorType(XmlAccessType.FIELD)
public class Arrival {
#XmlElement(name = "Airport")
private String Airport;
#XmlElement(name = "DateTime")
private String DateTime;
getters & setters go here
}
FareInfos
#XmlRootElement (name = "FareInfos")
#XmlAccessorType(XmlAccessType.FIELD)
public class FareInfos {
#XmlElement (name = "FareReference")
private String fareReference;
#XmlElement (name = "BaseAmount")
private String baseAmount;
#XmlElement (name ="TaxAmount")
private String taxAmount;
#XmlElement (name = "TotalFare" )
private String totalFare;
getters & setters go here
}
Since your XML document is namespace qualified you will need to use the package level #XmlSchema annotation to map the namespace qualification.
#XmlSchema(
namespace = "example.com",
elementFormDefault = XmlNsForm.QUALIFIED)
package example;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html

Categories