1 /*
2  * Copyright 2013 FasterXML.com
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may
5  * not use this file except in compliance with the License. You may obtain
6  * a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the license for the specific language governing permissions and
14  * limitations under the license.
15  */

16
17 package com.fasterxml.jackson.datatype.jsr310.deser;
18
19 import java.io.IOException;
20 import java.time.DateTimeException;
21 import java.time.YearMonth;
22 import java.time.format.DateTimeFormatter;
23
24 import com.fasterxml.jackson.annotation.JsonFormat;
25 import com.fasterxml.jackson.core.JsonParser;
26 import com.fasterxml.jackson.databind.DeserializationContext;
27 import com.fasterxml.jackson.databind.DeserializationFeature;
28 import com.fasterxml.jackson.core.JsonToken;
29
30 /**
31  * Deserializer for Java 8 temporal {@link YearMonth}s.
32  *
33  * @author Nick Williams
34  * @since 2.2.0
35  */

36 public class YearMonthDeserializer extends JSR310DateTimeDeserializerBase<YearMonth>
37 {
38     private static final long serialVersionUID = 1L;
39
40     public static final YearMonthDeserializer INSTANCE = new YearMonthDeserializer();
41
42     private YearMonthDeserializer()
43     {
44         this(DateTimeFormatter.ofPattern("uuuu-MM"));
45     }
46     
47     public YearMonthDeserializer(DateTimeFormatter formatter)
48     {
49         super(YearMonth.class, formatter);
50     }
51
52     /**
53      * Since 2.11
54      */

55     protected YearMonthDeserializer(YearMonthDeserializer base, Boolean leniency) {
56         super(base, leniency);
57     }
58
59     @Override
60     protected YearMonthDeserializer withDateFormat(DateTimeFormatter dtf)  {
61         return new YearMonthDeserializer(dtf);
62     }
63
64     @Override
65     protected YearMonthDeserializer withLeniency(Boolean leniency) {
66         return new YearMonthDeserializer(this, leniency);
67     }
68
69     @Override
70     protected YearMonthDeserializer withShape(JsonFormat.Shape shape) { return this; }
71
72     @Override
73     public YearMonth deserialize(JsonParser parser, DeserializationContext context) throws IOException
74     {
75         if (parser.hasToken(JsonToken.VALUE_STRING)) {
76             String string = parser.getText().trim();
77             if (string.length() == 0) {
78                 if (!isLenient()) {
79                     return _failForNotLenient(parser, context, JsonToken.VALUE_STRING);
80                 }
81                 return null;
82             }
83             try {
84                 return YearMonth.parse(string, _formatter);
85             } catch (DateTimeException e) {
86                 return _handleDateTimeException(context, e, string);
87             }
88         }
89         if (parser.isExpectedStartArrayToken()) {
90             JsonToken t = parser.nextToken();
91             if (t == JsonToken.END_ARRAY) {
92                 return null;
93             }
94             if ((t == JsonToken.VALUE_STRING || t == JsonToken.VALUE_EMBEDDED_OBJECT)
95                     && context.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
96                 final YearMonth parsed = deserialize(parser, context);
97                 if (parser.nextToken() != JsonToken.END_ARRAY) {
98                     handleMissingEndArrayForSingle(parser, context);
99                 }
100                 return parsed;            
101             }
102             if (t != JsonToken.VALUE_NUMBER_INT) {
103                 _reportWrongToken(context, JsonToken.VALUE_NUMBER_INT, "years");
104             }
105             int year = parser.getIntValue();
106             int month = parser.nextIntValue(-1);
107             if (month == -1) {
108                 if (!parser.hasToken(JsonToken.VALUE_NUMBER_INT)) {
109                     _reportWrongToken(context, JsonToken.VALUE_NUMBER_INT, "months");
110                 }
111                 month = parser.getIntValue();
112             }
113             if (parser.nextToken() != JsonToken.END_ARRAY) {
114                 throw context.wrongTokenException(parser, handledType(), JsonToken.END_ARRAY,
115                         "Expected array to end");
116             }
117             return YearMonth.of(year, month);
118         }
119         if (parser.hasToken(JsonToken.VALUE_EMBEDDED_OBJECT)) {
120             return (YearMonth) parser.getEmbeddedObject();
121         }
122         return _handleUnexpectedToken(context, parser,
123                 JsonToken.VALUE_STRING, JsonToken.START_ARRAY);
124     }
125 }
126