aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/fasterxml/jackson/databind/deser/std/JacksonDeserializers.java
blob: 2fbf85e5146aa7666ef231fae96a8104e447cb31 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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;
        }
    }
}