Reputation: 2809
I have a class that deserializes
a JSON
element.
public class DateTimeConverter implements JsonSerializer<DateTime>, JsonDeserializer<DateTime>
{
private static final DateTimeFormatter DATE_FORMAT = ISODateTimeFormat.dateHourMinuteSecondMillis();
@Override
public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context)
{
final DateTimeFormatter fmt = ISODateTimeFormat.dateHourMinuteSecondMillis();
return new JsonPrimitive(fmt.print(src));
}
@Override
public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException
{
final String dateAsString = json.getAsString();
System.out.println(dateAsString);
if (json.isJsonNull() || dateAsString.length()==0)
{
return null;
}
else
{
return DATE_FORMAT.parseDateTime(json.getAsString());
}
}
}
However, my Deserialize
method when I input:
2015-07-29T11:00:00.000Z
I receive:
2015-07-29T11
from the System.out.println(dateAsString);
Why is it truncating my input?
I think my issue is within my test class:
I constructed a DateTime
object to be used with Google's Gson. However, I think the default constructor for DateTimeType
doesn't support minute/second/millisecond. Is there a way I can extend the DateTimeType
to support it?
Here is my test class:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import org.joda.time.DateTime;
import org.junit.Test;
import java.lang.reflect.Type;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* Tests {@link DateTimeConverter}.
*/
public class DateTimeConverterTest {
String testTime = "2015-07-29T11:00:00.001Z";
@Test
public void testDateTimeConverter() throws Exception {
final Gson gson = initCustomGSON();
Type DateTimeType = new TypeToken<DateTime>() {
}.getType();
System.out.println(testTime);
DateTimeConverter timeConverter = new DateTimeConverter();
DateTime m = (gson.fromJson(testTime, DateTimeType));
assertThat("11", is(m.hourOfDay().getAsText()));
}
public Gson initCustomGSON() {
final GsonBuilder builder = new GsonBuilder();
JodaTimeConverters converter = new JodaTimeConverters();
converter.registerAll(builder);
return builder.create();
}
}
Upvotes: 2
Views: 1335
Reputation: 32323
You have a few issues with this code.
Your first problem is that :
is an operator in Json. You are interpreting an unescaped String
with a :
in it, so Gson is interpreting it as key
: value
. Your test string needs to surround the entire text date with quotes to prevent this from happening, e.g.
String testTime = "\"2015-07-29T11:00:00.001Z\"";
You were using ISODateTimeFormat.dateHourMinuteSecondMillis()
in your code. However, the format pattern for this is yyyy-MM-dd'T'HH:mm:ss.SSS
, which as you can see does not include a time zone. You want to be using ISODateTimeFormat.dateTime()
, whose pattern is yyyy-MM-dd'T'HH:mm:ss.SSSZZ
, which does have a time zone.
private static final DateTimeFormatter DATE_FORMAT = ISODateTimeFormat.dateTime();
Once these two changes are made, the DateTime
object is finally properly created... but it will be created in your local time zone, not in UTC (it will correctly adjust the time to your zone. You can easily switch this back to UTC by doing:
DateTime m = ((DateTime) (gson.fromJson(testTime, DateTimeType))).withZone(DateTimeZone.UTC);
Once you make these three changes, your tests will pass. However: I strongly advise against using JsonSerializer
and JsonDeserializer
, they have been deprecated in favor of TypeAdapter
, whose streaming API is significantly more performant:
New applications should prefer
TypeAdapter
, whose streaming API is more efficient than this interface's tree API.
I am aware the user guide provides code for how to do it with the JsonSerializer
/ JsonDeserializer
API, but that's just because they haven't yet updated it.
It would simply be something like this:
public class DateTimeAdapter extends TypeAdapter<DateTime> {
private static final DateTimeFormatter FORMAT = ISODateTimeFormat.dateTime();
public DateTime read(JsonReader reader) throws IOException {
if (reader.peek() == JsonToken.NULL) {
reader.nextNull();
return null;
}
String dateString = reader.nextString();
if(dateString.length() == 0) return null;
return FORMAT.parseDateTime(dateString);
}
public void write(JsonWriter writer, DateTime value) throws IOException {
if (value == null) {
writer.nullValue();
return;
}
writer.value(FORMAT.print(value));
}
}
Upvotes: 2