I am creating a service that receives requests in the form of JSON messages. I need to parse the message and take the appropriate action based on the request type. For example (in pseudo code):
switch(request.type) {
case "NewOrder":
createNewOrder(order);
break;
case "CancelOrder"
cancelOrder(orderId);
break;
}
It seems that most JSON APIs (at least those that do the object mapping for you) need the root object type to deserialize. Is there any elegant way around this?
As an example, in the Jackson API (using full object mapping), I need to call the mapper as follows:
NewOrder newOrder = mapper.readValue(src, NewOrder.class);
CancelOrder cancelOrder = mapper.readValue(src. CancelOrder.class);
Which means that I need to know the object's class even before I have parsed it. What I really need is some way to peek into the JSON string, determine the request type and then call the appropriate readValue() method - something like this:
String requestType = getRequestType(src);
switch(request.type) {
case "NewOrder":
NewOrder newOrder = mapper.readValue(src, NewOrder.class);
createNewOrder(newOrder.order);
break;
case "CancelOrder"
CancelOrder cancelOrder = mapper.readValue(src. CancelOrder.class);
cancelOrder(cancelOrder.orderId);
break;
}
Is it possible to do this using Jackson or any other Java JSON parser? I am sure I can go to a lower level and use a streaming API or a node based API, but trying to avoid that complexity if I can.
If you use Jackson to parse the JSON input into a Map, you can quickly access the type information. You can then create the object as the required class and use ObjectMapper.convert
to configure the object from the Map you got from Jackson.
Here is an example:
public class Test1 {
private String f;
private String b;
public void setFoo(String v) { f = v; }
public void setBim(String v) { b = v; }
public String toString() { return "f=" + f + ", b=" + b; }
public static void main(String[] args) throws Exception {
String test = "{ \"foo\":\"bar\", \"bim\":\"baz\" }";
ObjectMapper mapper = new ObjectMapper();
HashMap map = mapper.readValue(new StringReader(test), HashMap.class);
System.out.println(map);
Test1 test1 = mapper.convertValue(map, Test1.class);
System.out.println(test1);
}
}
You could use a wrapper around your order:
{
"NewOrder": {...}
}
or
{
"CancelOrder": {...}
}
UPDATE:
class Wrapper {
newOrder: NewOrder;
cancelOrderId: Integer;
}
Wrapper wrapper = mapper.readValue(src, Wrapper.class);
if (wrapper.newOrder != null) {
createNewOrder(wrapper.newOrder);
}
if (wrapper.cancelOrderId != null) {
cancelOrder(wrapper.cancelOrderId);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With