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.ser;
18
19 import com.fasterxml.jackson.annotation.JsonFormat;
20 import java.io.IOException;
21 import java.time.LocalDate;
22 import java.time.format.DateTimeFormatter;
23
24 import com.fasterxml.jackson.core.JsonGenerator;
25 import com.fasterxml.jackson.core.JsonToken;
26 import com.fasterxml.jackson.core.type.WritableTypeId;
27 import com.fasterxml.jackson.databind.*;
28 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
29 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonStringFormatVisitor;
30 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonValueFormat;
31 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
32
33 /**
34  * Serializer for Java 8 temporal {@link LocalDate}s.
35  *
36  * @author Nick Williams
37  * @since 2.2
38  */

39 public class LocalDateSerializer extends JSR310FormattedSerializerBase<LocalDate>
40 {
41     private static final long serialVersionUID = 1L;
42
43     public static final LocalDateSerializer INSTANCE = new LocalDateSerializer();
44
45     protected LocalDateSerializer() {
46         super(LocalDate.class);
47     }
48
49     protected LocalDateSerializer(LocalDateSerializer base,
50                                   Boolean useTimestamp, DateTimeFormatter dtf, JsonFormat.Shape shape) {
51         super(base, useTimestamp, dtf, shape);
52     }
53
54     public LocalDateSerializer(DateTimeFormatter formatter) {
55         super(LocalDate.class, formatter);
56     }
57
58     @Override
59     protected LocalDateSerializer withFormat(Boolean useTimestamp, DateTimeFormatter dtf, JsonFormat.Shape shape) {
60         return new LocalDateSerializer(this, useTimestamp, dtf, shape);
61     }
62
63     @Override
64     public void serialize(LocalDate date, JsonGenerator g, SerializerProvider provider) throws IOException
65     {
66         if (useTimestamp(provider)) {
67             if (_shape == JsonFormat.Shape.NUMBER_INT) {
68                 g.writeNumber(date.toEpochDay());
69             } else {
70                 g.writeStartArray();
71                 _serializeAsArrayContents(date, g, provider);
72                 g.writeEndArray();
73             }
74         } else {
75             g.writeString((_formatter == null) ? date.toString() : date.format(_formatter));
76         }
77     }
78
79     @Override
80     public void serializeWithType(LocalDate value, JsonGenerator g,
81             SerializerProvider provider, TypeSerializer typeSer) throws IOException
82     {
83         WritableTypeId typeIdDef = typeSer.writeTypePrefix(g,
84                 typeSer.typeId(value, serializationShape(provider)));
85         // need to write out to avoid double-writing array markers
86         switch (typeIdDef.valueShape) {
87         case START_ARRAY:
88             _serializeAsArrayContents(value, g, provider);
89             break;
90         case VALUE_NUMBER_INT:
91             g.writeNumber(value.toEpochDay());
92             break;
93         default:
94             g.writeString((_formatter == null) ? value.toString() : value.format(_formatter));
95         }
96         typeSer.writeTypeSuffix(g, typeIdDef);
97     }
98
99     protected void _serializeAsArrayContents(LocalDate value, JsonGenerator g,
100             SerializerProvider provider) throws IOException
101     {
102         g.writeNumber(value.getYear());
103         g.writeNumber(value.getMonthValue());
104         g.writeNumber(value.getDayOfMonth());
105     }
106
107     @Override
108     public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException
109     {
110         SerializerProvider provider = visitor.getProvider();
111         boolean useTimestamp = (provider != null) && useTimestamp(provider);
112         if (useTimestamp) {
113             _acceptTimestampVisitor(visitor, typeHint);
114         } else {
115             JsonStringFormatVisitor v2 = visitor.expectStringFormat(typeHint);
116             if (v2 != null) {
117                 v2.format(JsonValueFormat.DATE);
118             }
119         }
120     }
121
122     @Override // since 2.9
123     protected JsonToken serializationShape(SerializerProvider provider) {
124         if (useTimestamp(provider)) {
125             if (_shape == JsonFormat.Shape.NUMBER_INT) {
126                 return JsonToken.VALUE_NUMBER_INT;
127             }
128             return JsonToken.START_ARRAY;
129         }
130         return JsonToken.VALUE_STRING;
131     }
132 }
133