Java Generics for unmarshall JAXB Object
10,007
Solution 1
Yes, you can enhance your code a little bit:
protected static <T> T unmarshall(String xml, Class<T> clazz)
throws JAXBException {
JAXBContext jc = JAXBContext.newInstance(clazz);
Unmarshaller unmarshaller = jc.createUnmarshaller();
T obj = clazz.cast(unmarshaller.unmarshal(new StringReader(xml)));
return obj;
}
Solution 2
If you don't need/want to reuse the JAXBContext, no need to create it. There is a convenience method that (almost) has the method signature you want. It throws a RuntimeException
(many prefer that).
protected static <T> T unmarshall(String xml, Class<T> clazz) {
return JAXB.unmarshal(new StringReader(xml), clazz);
}
But imo, just use the method directly without a wrapper.
Reusing a JAXBContext
makes (un)marshalling faster in the long run. Another improvement is clazz.cast()
to avoid the nasty unchecked cast
private static final ConcurrentMap<Class<?>, JAXBContext> CONTEXT = new ConcurrentHashMap<>();
protected static <T> T unmarshall(String xml, Class<T> clazz)
throws JAXBException {
JAXBContext context = CONTEXT.get(clazz);
if (context == null){
context = JAXBContext.newInstance(clazz);
CONTEXT.putIfAbsent(clazz, context);
}
Unmarshaller unmarshaller = context.createUnmarshaller();
Object obj = unmarshaller.unmarshal(new StringReader(xml));
if (clazz.isInstance(obj)){
return clazz.cast(obj);
}
throw new IllegalArgumentException("XML does not represent an instance of type:" + clazz.getName());
}
Comments
-
Vel almost 2 years
I have the below code to unmarshall xml into Java objects. I would like to see if this code can be enhanced by using Java Generics instead of using Object type as return value.
protected static <T> Object unmarshall(String xml, Class<T> clazz) throws JAXBException { JAXBContext jc = JAXBContext.newInstance(clazz); Unmarshaller unmarshaller = jc.createUnmarshaller(); Object obj = unmarshaller.unmarshal(new StringReader(xml)); return obj; }
Any suggestions.
-
Vel over 7 yearsThanks for the input!
-
VGR over 7 yearsSuppressWarnings is a quick-and-dirty workaround that hides programmer mistakes. Why not use the typesafe version instead:
T obj = unmarshaller.unmarshal(new StreamSource(new StringReader(xml)), clazz).getValue();
-
k5_ over 7 years@VGR that will bind the class to any rootelement (ignoring the actual name of the root element). Even if there is a better match in the context. A better way is to use clazz.isInstance() and clazz.cast() to avoid the unchecked cast and provide an expected result.
-
Thomas Fritsch over 7 yearsedited: now avoiding ugly
@SuppressWarnings
by usingclazz.cast()