1
16
17 package com.fasterxml.jackson.datatype.jsr310.deser;
18
19 import com.fasterxml.jackson.annotation.JsonFormat;
20 import com.fasterxml.jackson.core.JsonParser;
21 import com.fasterxml.jackson.core.JsonToken;
22 import com.fasterxml.jackson.core.JsonTokenId;
23 import com.fasterxml.jackson.databind.BeanProperty;
24 import com.fasterxml.jackson.databind.DeserializationContext;
25 import com.fasterxml.jackson.databind.DeserializationFeature;
26 import com.fasterxml.jackson.databind.JsonDeserializer;
27 import com.fasterxml.jackson.databind.JsonMappingException;
28 import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
29 import com.fasterxml.jackson.datatype.jsr310.DecimalUtils;
30
31 import java.io.IOException;
32 import java.math.BigDecimal;
33 import java.time.DateTimeException;
34 import java.time.Duration;
35
36
37
43 public class DurationDeserializer extends JSR310DeserializerBase<Duration> implements ContextualDeserializer
44 {
45 private static final long serialVersionUID = 1L;
46
47 public static final DurationDeserializer INSTANCE = new DurationDeserializer();
48
49 private DurationDeserializer()
50 {
51 super(Duration.class);
52 }
53
54
57 protected DurationDeserializer(DurationDeserializer base, Boolean leniency) {
58 super(base, leniency);
59 }
60
61 @Override
62 protected DurationDeserializer withLeniency(Boolean leniency) {
63 return new DurationDeserializer(this, leniency);
64 }
65
66 @Override
67 public Duration deserialize(JsonParser parser, DeserializationContext context) throws IOException
68 {
69 switch (parser.getCurrentTokenId())
70 {
71 case JsonTokenId.ID_NUMBER_FLOAT:
72 BigDecimal value = parser.getDecimalValue();
73 return DecimalUtils.extractSecondsAndNanos(value, Duration::ofSeconds);
74
75 case JsonTokenId.ID_NUMBER_INT:
76 if(context.isEnabled(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)) {
77 return Duration.ofSeconds(parser.getLongValue());
78 }
79 return Duration.ofMillis(parser.getLongValue());
80
81 case JsonTokenId.ID_STRING:
82 String string = parser.getText().trim();
83 if (string.length() == 0) {
84 if (!isLenient()) {
85 return _failForNotLenient(parser, context, JsonToken.VALUE_STRING);
86 }
87 return null;
88 }
89 try {
90 return Duration.parse(string);
91 } catch (DateTimeException e) {
92 return _handleDateTimeException(context, e, string);
93 }
94 case JsonTokenId.ID_EMBEDDED_OBJECT:
95
96
97 return (Duration) parser.getEmbeddedObject();
98
99 case JsonTokenId.ID_START_ARRAY:
100 return _deserializeFromArray(parser, context);
101 }
102 return _handleUnexpectedToken(context, parser, JsonToken.VALUE_STRING,
103 JsonToken.VALUE_NUMBER_INT, JsonToken.VALUE_NUMBER_FLOAT);
104 }
105
106 @Override
107 public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
108 BeanProperty property) throws JsonMappingException
109 {
110 JsonFormat.Value format = findFormatOverrides(ctxt, property, handledType());
111 DurationDeserializer deser = this;
112 if (format != null) {
113 if (format.hasLenient()) {
114 Boolean leniency = format.getLenient();
115 if (leniency != null) {
116 deser = deser.withLeniency(leniency);
117 }
118 }
119 }
120 return deser;
121 }
122 }
123