| 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.DeserializationContext; |
| import com.fasterxml.jackson.databind.JavaType; |
| import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; |
| import com.fasterxml.jackson.databind.cfg.DeserializationConfig; |
| 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; |
| } |
| } |
| } |