blob: 2a5bd97e27c252fa14015b5771658b8a02e75411 [file] [log] [blame]
package org.codehaus.jackson.xc;
import java.io.IOException;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.*;
import org.codehaus.jackson.map.deser.std.StdDeserializer;
import org.codehaus.jackson.map.type.TypeFactory;
import org.codehaus.jackson.type.JavaType;
/**
* @author Ryan Heaton
* @author Tatu Saloranta
*/
public class XmlAdapterJsonDeserializer
extends StdDeserializer<Object>
{
protected final static JavaType ADAPTER_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(XmlAdapter.class);
protected final XmlAdapter<Object,Object> _xmlAdapter;
protected final JavaType _valueType;
protected JsonDeserializer<?> _deserializer;
public XmlAdapterJsonDeserializer(XmlAdapter<Object,Object> xmlAdapter)
{
super(Object.class); // type not yet known (will be in a second), but that's ok...
_xmlAdapter = xmlAdapter;
// [JACKSON-404] Need to figure out generic type parameters used...
/* 14-Mar-2011, tatu: This is sub-optimal, as we really should use
* configured TypeFactory, not global one; but it should not cause
* issues here (issue would be that it will ignore module-provided additional
* type manging, most relevant for languages other than Java)
*/
TypeFactory typeFactory = TypeFactory.defaultInstance();
JavaType type = typeFactory.constructType(xmlAdapter.getClass());
JavaType[] rawTypes = typeFactory.findTypeParameters(type, XmlAdapter.class);
_valueType = (rawTypes == null || rawTypes.length == 0)
? TypeFactory.unknownType() : rawTypes[0];
}
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
/* Unfortunately we can not use the usual resolution mechanism (ResolvableDeserializer)
* because it won't get called due to way adapters are created. So, need to do it
* lazily when we get here:
*/
JsonDeserializer<?> deser = _deserializer;
if (deser == null) {
DeserializationConfig config = ctxt.getConfig();
_deserializer = deser = ctxt.getDeserializerProvider().findValueDeserializer
(config, _valueType, null);
}
Object boundObject = deser.deserialize(jp, ctxt);
try {
return _xmlAdapter.unmarshal(boundObject);
} catch (Exception e) {
throw new JsonMappingException("Unable to unmarshal (to type "+_valueType+"): "+e.getMessage(), e);
}
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
TypeDeserializer typeDeserializer)
throws IOException, JsonProcessingException
{
// Output can be as JSON Object, Array or scalar: no way to know a priori. So:
return typeDeserializer.deserializeTypedFromAny(jp, ctxt);
}
}