I need to deserialize this in Java 1.7 with Jackson, using currency as value:
"prices": {
"USD": [
[1, "1.99000"],
[100, "1.89000"],
[1000, "1.40500"]
],
"EUR": [
[1, "1.53000"],
[100, "1.45000"],
[1000, "1.08350"]
]
}
(source is this REST API https://octopart.com/api/docs/v3/rest-api#notes-partoffer.prices)
My goal is to get objects for each Price with attributes currency, price break and price.
I can't figure out how to perform that. I tried the following:
deserialize the whole "prices" as String for further processing (didn't work, got Can not deserialize instance of java.lang.String out of START_OBJECT token - obviously, since this is JSON_OBJECT)
deserialize like
LinkedHashMap<String, LinkedHashMap<Integer, String>>>
(inspired by this Deserializing Jackson by using a key as value, but also didn't work)
use a wrapper like this:
public class PartOfferPriceWrapper { private LinkedHashMap<String, List<Entry<Integer, String>>> prices; }
and then process like:
List<PartOfferPrice> partOfferPriceList = new ArrayList<PartOfferPrice>();
for (Entry<String, List<Entry<Integer, String>>> currencyEntry :
partOfferPrices.entrySet()) {
for (Entry<Integer, String> priceEntry : currencyEntry.getValue()) {
PartOfferPrice partOfferPrice = new PartOfferPrice();
partOfferPrice.setOffer_id(partOfferId);
partOfferPrice.setCurrency(currencyEntry.getKey());
partOfferPrice.setPriceBreak(priceEntry.getKey());
partOfferPrice.setPrice(Double.parseDouble(priceEntry.getValue()));
partOfferPriceList.add(partOfferPrice);
}
This seems fine, but the result is empty (it's a part of bigger response, reading with Response.readEntity was successful). I can't find any other way how to process this (some custom deserializer?).
EDIT
I tried to use custom deserializer following tima's advice:
public class PartOfferPricesWrapperDeserializer extends
JsonDeserializer<PartOfferPricesWrapper> {
public PartOfferPricesWrapperDeserializer() { super(); }
@Override
public PartOfferPricesWrapper deserialize(JsonParser jsonParser,
DeserializationContext context) throws IOException,
JsonProcessingException {
PartOfferPricesWrapper partOfferPricesWrapper = new
PartOfferPricesWrapper();
List<PartOfferPrice> priceList = new ArrayList<PartOfferPrice>();
JsonNode node = jsonParser.readValueAsTree();
Iterator<Entry<String, JsonNode>> nodes =
node.get("prices").fields();
while (nodes.hasNext()) {
Map.Entry<String, JsonNode> entry = nodes.next();
for (JsonNode tempNode : entry.getValue()) {
PartOfferPrice price = new PartOfferPrice();
price.setCurrency(entry.getKey());
for (int i = 0; i < tempNode.size(); i++) {
if (tempNode.get(i).isInt()) {
price.setPriceBreak(tempNode.get(i).intValue());
}
else
{
price.setPrice(tempNode.get(i).asDouble());
}
}
priceList.add(price);
}
}
partOfferPricesWrapper.setPrices(priceList);
return partOfferPricesWrapper;
}
}
adding this to the handler method:
SimpleModule module = new SimpleModule();
module.addDeserializer(PartOfferPricesWrapper.class, new
PartOfferPricesWrapperDeserializer());
objectMapper.registerModule(module);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
false);
partsMatchResponse = objectMapper.readValue(target.getUri().toURL(),
PartsMatchResponse.class);
Which would probably work if the response contains only "prices" node, but now I'm getting NullPointerException on node.get("prices").fields(); It is probably trying to parse the whole response, but I need to use the custom deserializer only for the "prices" part. Is it somehow possible?
Thanks a lot.