package com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.deser.CreatorProperty; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * Container class for core Jackson type deserializers. */ public class JacksonDeserializers { public static StdDeserializer<?>[] all() { // note: JsonLocation supported via ValueInstantiator return new StdDeserializer[] { new JavaTypeDeserializer(), new TokenBufferDeserializer(), }; } public static ValueInstantiator findValueInstantiator(DeserializationConfig config, BeanDescription beanDesc) { if (beanDesc.getBeanClass() == JsonLocation.class) { return new JsonLocationInstantiator(); } return null; } /* /********************************************************** /* Deserializer implementations /********************************************************** */ /** * Deserializer for {@link JavaType} values. */ public static class JavaTypeDeserializer extends StdScalarDeserializer<JavaType> { public JavaTypeDeserializer() { super(JavaType.class); } @Override public JavaType deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { JsonToken curr = jp.getCurrentToken(); // Usually should just get string value: if (curr == JsonToken.VALUE_STRING) { String str = jp.getText().trim(); if (str.length() == 0) { return getEmptyValue(); } return ctxt.getTypeFactory().constructFromCanonical(str); } // or occasionally just embedded object maybe if (curr == JsonToken.VALUE_EMBEDDED_OBJECT) { return (JavaType) jp.getEmbeddedObject(); } throw ctxt.mappingException(_valueClass); } } /** * For {@link JsonLocation}, we should be able to just implement * {@link ValueInstantiator} (not that explicit one would be very * hard but...) */ public static class JsonLocationInstantiator extends ValueInstantiator { @Override public String getValueTypeDesc() { return JsonLocation.class.getName(); } @Override public boolean canCreateFromObjectWith() { return true; } @Override public CreatorProperty[] getFromObjectArguments(DeserializationConfig config) { JavaType intType = config.constructType(Integer.TYPE); JavaType longType = config.constructType(Long.TYPE); return new CreatorProperty[] { new CreatorProperty("sourceRef", config.constructType(Object.class), null, null, null, 0, null), new CreatorProperty("byteOffset", longType, null, null, null, 1, null), new CreatorProperty("charOffset", longType, null, null, null, 2, null), new CreatorProperty("lineNr", intType, null, null, null, 3, null), new CreatorProperty("columnNr", intType, null, null, null, 4, null) }; } @Override public Object createFromObjectWith(DeserializationContext ctxt, Object[] args) { return new JsonLocation(args[0], _long(args[1]), _long(args[2]), _int(args[3]), _int(args[4])); } private final static long _long(Object o) { return (o == null) ? 0L : ((Number) o).longValue(); } private final static int _int(Object o) { return (o == null) ? 0 : ((Number) o).intValue(); } } /** * We also want to directly support deserialization of {@link TokenBuffer}. *<p> * Note that we use scalar deserializer base just because we claim * to be of scalar for type information inclusion purposes; actual * underlying content can be of any (Object, Array, scalar) type. */ @JacksonStdImpl public static class TokenBufferDeserializer extends StdScalarDeserializer<TokenBuffer> { public TokenBufferDeserializer() { super(TokenBuffer.class); } @Override public TokenBuffer deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { TokenBuffer tb = new TokenBuffer(jp.getCodec()); // quite simple, given that TokenBuffer is a JsonGenerator: tb.copyCurrentStructure(jp); return tb; } } }