1
16
17 package com.fasterxml.jackson.datatype.jsr310.deser;
18
19 import java.io.IOException;
20 import java.time.DateTimeException;
21 import java.time.Period;
22 import java.time.ZoneId;
23 import java.time.ZoneOffset;
24
25 import com.fasterxml.jackson.annotation.JsonFormat;
26 import com.fasterxml.jackson.core.JsonParser;
27
28 import com.fasterxml.jackson.core.JsonToken;
29 import com.fasterxml.jackson.databind.BeanProperty;
30 import com.fasterxml.jackson.databind.DeserializationContext;
31 import com.fasterxml.jackson.databind.JsonDeserializer;
32 import com.fasterxml.jackson.databind.JsonMappingException;
33 import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
34 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
35
36
46 public class JSR310StringParsableDeserializer
47 extends JSR310DeserializerBase<Object>
48 implements ContextualDeserializer
49 {
50 private static final long serialVersionUID = 1L;
51
52 protected final static int TYPE_PERIOD = 1;
53 protected final static int TYPE_ZONE_ID = 2;
54 protected final static int TYPE_ZONE_OFFSET = 3;
55
56 public static final JsonDeserializer<Period> PERIOD =
57 createDeserializer(Period.class, TYPE_PERIOD);
58
59 public static final JsonDeserializer<ZoneId> ZONE_ID =
60 createDeserializer(ZoneId.class, TYPE_ZONE_ID);
61
62 public static final JsonDeserializer<ZoneOffset> ZONE_OFFSET =
63 createDeserializer(ZoneOffset.class, TYPE_ZONE_OFFSET);
64
65 protected final int _typeSelector;
66
67 @SuppressWarnings("unchecked")
68 protected JSR310StringParsableDeserializer(Class<?> supportedType, int typeSelector)
69 {
70 super((Class<Object>)supportedType);
71 _typeSelector = typeSelector;
72 }
73
74
77 protected JSR310StringParsableDeserializer(JSR310StringParsableDeserializer base, Boolean leniency) {
78 super(base, leniency);
79 _typeSelector = base._typeSelector;
80 }
81
82 @SuppressWarnings("unchecked")
83 protected static <T> JsonDeserializer<T> createDeserializer(Class<T> type, int typeId) {
84 return (JsonDeserializer<T>) new JSR310StringParsableDeserializer(type, typeId);
85 }
86
87 @Override
88 protected JSR310StringParsableDeserializer withLeniency(Boolean leniency) {
89 if (_isLenient == !Boolean.FALSE.equals(leniency)) {
90 return this;
91 }
92
93
94 return new JSR310StringParsableDeserializer(this, leniency);
95 }
96
97 @Override
98 public Object deserialize(JsonParser p, DeserializationContext context) throws IOException
99 {
100 String string = p.getValueAsString();
101 if (string != null) {
102 string = string.trim();
103 if (string.length() == 0) {
104 if (!isLenient()) {
105 return _failForNotLenient(p, context, JsonToken.VALUE_STRING);
106 }
107 return null;
108 }
109 try {
110 switch (_typeSelector) {
111 case TYPE_PERIOD:
112 return Period.parse(string);
113 case TYPE_ZONE_ID:
114 return ZoneId.of(string);
115 case TYPE_ZONE_OFFSET:
116 return ZoneOffset.of(string);
117 }
118 } catch (DateTimeException e) {
119 return _handleDateTimeException(context, e, string);
120 }
121 }
122 if (p.hasToken(JsonToken.VALUE_EMBEDDED_OBJECT)) {
123
124
125 return p.getEmbeddedObject();
126 }
127 if (p.hasToken(JsonToken.START_ARRAY)){
128 return _deserializeFromArray(p, context);
129 }
130
131 throw context.wrongTokenException(p, handledType(), JsonToken.VALUE_STRING, null);
132 }
133
134 @Override
135 public Object deserializeWithType(JsonParser parser, DeserializationContext context,
136 TypeDeserializer deserializer)
137 throws IOException
138 {
139
140
141 JsonToken t = parser.getCurrentToken();
142 if ((t != null) && t.isScalarValue()) {
143 return deserialize(parser, context);
144 }
145 return deserializer.deserializeTypedFromAny(parser, context);
146 }
147
148 @Override
149 public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
150 BeanProperty property) throws JsonMappingException
151 {
152 JsonFormat.Value format = findFormatOverrides(ctxt, property, handledType());
153 JSR310StringParsableDeserializer deser = this;
154 if (format != null) {
155 if (format.hasLenient()) {
156 Boolean leniency = format.getLenient();
157 if (leniency != null) {
158 deser = this.withLeniency(leniency);
159 }
160 }
161 }
162 return deser;
163 }
164 }
165