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

37 public class LocalDateTimeSerializer extends JSR310FormattedSerializerBase<LocalDateTime>
38 {
39     private static final long serialVersionUID = 1L;
40
41     public static final LocalDateTimeSerializer INSTANCE = new LocalDateTimeSerializer();
42     
43     protected LocalDateTimeSerializer() {
44         this(null);
45     }
46
47     public LocalDateTimeSerializer(DateTimeFormatter f) {
48         super(LocalDateTime.class, f);
49     }
50
51     private LocalDateTimeSerializer(LocalDateTimeSerializer base, Boolean useTimestamp, Boolean useNanoseconds, DateTimeFormatter f) {
52         super(base, useTimestamp, useNanoseconds, f, null);
53     }
54
55     @Override
56     protected JSR310FormattedSerializerBase<LocalDateTime> withFormat(Boolean useTimestamp, DateTimeFormatter f, JsonFormat.Shape shape) {
57         return new LocalDateTimeSerializer(this, useTimestamp, _useNanoseconds, f);
58     }
59
60     protected DateTimeFormatter _defaultFormatter() {
61         return DateTimeFormatter.ISO_LOCAL_DATE_TIME;
62     }
63
64     @Override
65     public void serialize(LocalDateTime value, JsonGenerator g, SerializerProvider provider)
66         throws IOException
67     {
68         if (useTimestamp(provider)) {
69             g.writeStartArray();
70             _serializeAsArrayContents(value, g, provider);
71             g.writeEndArray();
72         } else {
73             DateTimeFormatter dtf = _formatter;
74             if (dtf == null) {
75                 dtf = _defaultFormatter();
76             }
77             g.writeString(value.format(dtf));
78         }
79     }
80
81     @Override
82     public void serializeWithType(LocalDateTime value, JsonGenerator g, SerializerProvider provider,
83             TypeSerializer typeSer) throws IOException
84     {
85         WritableTypeId typeIdDef = typeSer.writeTypePrefix(g,
86                 typeSer.typeId(value, serializationShape(provider)));
87         // need to write out to avoid double-writing array markers
88         if (typeIdDef.valueShape == JsonToken.START_ARRAY) {
89             _serializeAsArrayContents(value, g, provider);
90         } else {
91             DateTimeFormatter dtf = _formatter;
92             if (dtf == null) {
93                 dtf = _defaultFormatter();
94             }
95             g.writeString(value.format(dtf));
96         }
97         typeSer.writeTypeSuffix(g, typeIdDef);
98     }
99
100     private final void _serializeAsArrayContents(LocalDateTime value, JsonGenerator g,
101             SerializerProvider provider) throws IOException
102     {
103         g.writeNumber(value.getYear());
104         g.writeNumber(value.getMonthValue());
105         g.writeNumber(value.getDayOfMonth());
106         g.writeNumber(value.getHour());
107         g.writeNumber(value.getMinute());
108         final int secs = value.getSecond();
109         final int nanos = value.getNano();
110         if ((secs > 0) || (nanos > 0)) {
111             g.writeNumber(secs);
112             if (nanos > 0) {
113                 if (useNanoseconds(provider)) {
114                     g.writeNumber(nanos);
115                 } else {
116                     g.writeNumber(value.get(ChronoField.MILLI_OF_SECOND));
117                 }
118             }
119         }
120     }
121
122     @Override // since 2.9
123     protected JsonToken serializationShape(SerializerProvider provider) {
124         return useTimestamp(provider) ? JsonToken.START_ARRAY : JsonToken.VALUE_STRING;
125     }
126
127     @Override
128     protected JSR310FormattedSerializerBase<?> withFeatures(Boolean writeZoneId, Boolean writeNanoseconds) {
129         return new LocalDateTimeSerializer(this, _useTimestamp, writeNanoseconds, _formatter);
130     }
131 }
132