Skip to content

Commit

Permalink
Merge pull request #1167 from rgoldberg/parse-xml-gregorian-calendar-…
Browse files Browse the repository at this point in the history
…lexical-representation

Deserialize time-only XMLGregorianCalendar
  • Loading branch information
cowtowncoder committed Apr 3, 2016
2 parents 1033ebd + cf2c9ba commit 661867b
Showing 1 changed file with 65 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.Deserializers;
import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;

/**
* Container deserializers that handle "core" XML types: ones included in standard
Expand Down Expand Up @@ -65,7 +66,7 @@ public JsonDeserializer<?> findBeanDeserializer(JavaType type,
* javax.xml types {@link QName}, {@link Duration} and {@link XMLGregorianCalendar}.
* Combined into a single class to eliminate bunch of one-off implementation
* classes, to reduce resulting jar size (mostly).
*
*
* @since 2.4
*/
public static class Std extends FromStringDeserializer<Object>
Expand All @@ -85,19 +86,72 @@ public Object deserialize(JsonParser jp, DeserializationContext ctxt)
{
// For most types, use super impl; but not for GregorianCalendar
if (_kind == TYPE_G_CALENDAR) {
Date d = _parseDate(jp, ctxt);
if (d == null) {
return null;
return parseXMLGregorianCalendarPossiblyNested(jp, ctxt);
}
return super.deserialize(jp, ctxt);
}

protected XMLGregorianCalendar parseXMLGregorianCalendarPossiblyNested(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
// Must unnest nested arrays here using iteration instead of in _parseDate(...) using recursion
// because if _parseDate(...) throws an exception, then this must try to parse using _dataTypeFactory.newXMLGregorianCalendar(String)
// which would lose the recursive array nesting context from _parseDate(...)

int nestedArrayCount = 0;
for (JsonToken t = jp.getCurrentToken(); t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); t = jp.nextToken()) {
nestedArrayCount++;
}

final XMLGregorianCalendar xgCal = parseXMLGregorianCalendarNotNested(jp, ctxt);

for (int i = 0; i < nestedArrayCount; i++) {
if (jp.nextToken() != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(
jp,
JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single 'javax.xml.datatype.XMLGregorianCalendar' value but there was more than a single value in the array"
);
}
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(d);
TimeZone tz = ctxt.getTimeZone();
if (tz != null) {
calendar.setTimeZone(tz);
}

return xgCal;
}

protected XMLGregorianCalendar parseXMLGregorianCalendarNotNested(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
try {
return parseXMLGregorianCalendarFromJacksonFormat(jp, ctxt);
}
catch (InvalidFormatException e) {
// try to parse from native XML Schema 1.0 lexical representation String,
// which includes time-only formats not handled by parseXMLGregorianCalendarFromJacksonFormat(...)

JsonToken t = jp.getCurrentToken();

if (t == JsonToken.VALUE_STRING) {
return _dataTypeFactory.newXMLGregorianCalendar(jp.getText().trim());
}
return _dataTypeFactory.newXMLGregorianCalendar(calendar);

throw ctxt.mappingException(_valueClass, t);
}
return super.deserialize(jp, ctxt);
}

protected XMLGregorianCalendar parseXMLGregorianCalendarFromJacksonFormat(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
Date d = _parseDate(jp, ctxt);
if (d == null) {
return null;
}
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(d);
TimeZone tz = ctxt.getTimeZone();
if (tz != null) {
calendar.setTimeZone(tz);
}
return _dataTypeFactory.newXMLGregorianCalendar(calendar);
}

@Override
Expand Down

0 comments on commit 661867b

Please sign in to comment.