Skip to content

Commit

Permalink
Merge pull request #24 from pavanpvpk/ZoneIdConverter
Browse files Browse the repository at this point in the history
Add ZoneId converter
  • Loading branch information
gkopff committed Jul 13, 2022
2 parents 273d706 + c189abc commit 2fb0fbb
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 19 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ target
.idea/libraries/
.idea/scala_settings.xml
.idea/dictionaries/
*.ipr
*.iws

# Mac
.DS_Store
18 changes: 0 additions & 18 deletions gson-javatime-serialisers.iml

This file was deleted.

19 changes: 18 additions & 1 deletion src/main/java/com/fatboyindustrial/gsonjavatime/Converters.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

/**
Expand Down Expand Up @@ -62,6 +63,9 @@ public class Converters
/** The specific genericized type for {@code Instant}. */
public static final Type INSTANT_TYPE = new TypeToken<Instant>(){}.getType();

/** The specific genericized type for {@code ZoneId}. */
public static final Type ZONE_ID_TYPE = new TypeToken<ZoneId>(){}.getType();

/**
* Registers all the Java Time converters.
* @param builder The GSON builder to register the converters with.
Expand All @@ -78,6 +82,7 @@ public static GsonBuilder registerAll(GsonBuilder builder)
registerOffsetTime(builder);
registerZonedDateTime(builder);
registerInstant(builder);
registerZoneId(builder);

return builder;
}
Expand Down Expand Up @@ -162,7 +167,19 @@ public static GsonBuilder registerZonedDateTime(GsonBuilder builder)
public static GsonBuilder registerInstant(GsonBuilder builder)
{
builder.registerTypeAdapter(INSTANT_TYPE, new InstantConverter());

return builder;
}

/**
* Registers the {@link ZoneIdConverter} converter.
* @param builder The GSON builder to register the converter with.
* @return A reference to {@code builder}.
*/
public static GsonBuilder registerZoneId(GsonBuilder builder)
{
builder.registerTypeAdapter(ZONE_ID_TYPE, new ZoneIdConverter());

return builder;
}
}
100 changes: 100 additions & 0 deletions src/main/java/com/fatboyindustrial/gsonjavatime/ZoneIdConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright 2014 Greg Kopff
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.fatboyindustrial.gsonjavatime;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

import java.lang.reflect.Type;
import java.time.ZoneId;

/**
* GSON serialiser/deserialiser for converting {@link ZoneId} objects.
*/
public class ZoneIdConverter implements JsonSerializer<ZoneId>, JsonDeserializer<ZoneId> {

/**
* Gson invokes this call-back method during serialization when it encounters a field of the
* specified type. <p>
*
* In the implementation of this call-back method, you should consider invoking
* {@link JsonSerializationContext#serialize(Object, Type)} method to create JsonElements for any
* non-trivial field of the {@code src} object. However, you should never invoke it on the
* {@code src} object itself since that will cause an infinite loop (Gson will call your
* call-back method again).
*
* @param src the object that needs to be converted to Json.
* @param typeOfSrc the actual type (fully genericized version) of the source object.
* @return a JsonElement corresponding to the specified object.
*/
@Override
public JsonElement serialize(final ZoneId src, final Type typeOfSrc, final JsonSerializationContext context)
{
if (src == null)
{
return null;
}
return new JsonPrimitive(src.getId());
}

/**
* Gson invokes this call-back method during deserialization when it encounters a field of the
* specified type. <p>
*
* In the implementation of this call-back method, you should consider invoking
* {@link JsonDeserializationContext#deserialize(JsonElement, Type)} method to create objects
* for any non-trivial field of the returned object. However, you should never invoke it on the
* the same type passing {@code json} since that will cause an infinite loop (Gson will call your
* call-back method again).
*
* @param json The Json data being deserialized
* @param typeOfT The type of the Object to deserialize to
* @return a deserialized object of the specified type typeOfT which is a subclass of {@code T}
* @throws JsonParseException if json is not in the expected format of {@code typeOfT}
*/
@Override
public ZoneId deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws
JsonParseException
{
if (json == null)
{
return null;
}
if (json.isJsonNull())
{
return null;
}
final String zoneIdentifier = json.getAsString();
if (zoneIdentifier==null || zoneIdentifier.isEmpty())
{
return null;
}
return ZoneId.of(zoneIdentifier);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public void testSerialisation() throws Exception
container.ot = OffsetTime.of(container.lt, ZoneOffset.ofHours(10));
container.zdt = ZonedDateTime.of(container.ld, container.lt, ZoneId.of("Australia/Brisbane"));
container.i = container.odt.toInstant();
container.zi = ZoneId.of("Australia/Brisbane");

final String jsonString = gson.toJson(container);
final JsonObject json = gson.fromJson(jsonString, JsonObject.class).getAsJsonObject();
Expand All @@ -74,6 +75,7 @@ public void testSerialisation() throws Exception
assertThat(json.get("ot").getAsString(), is("12:56:00+10:00"));
assertThat(json.get("zdt").getAsString(), is("1969-07-21T12:56:00+10:00[Australia/Brisbane]"));
assertThat(json.get("i").getAsString(), is("1969-07-21T02:56:00Z"));
assertThat(json.get("zi").getAsString(), is("Australia/Brisbane"));
}

/**
Expand All @@ -92,6 +94,7 @@ public void testDeserialisation() throws Exception
container.ot = OffsetTime.of(container.lt, ZoneOffset.ofHours(10));
container.zdt = ZonedDateTime.of(container.ld, container.lt, ZoneId.of("Australia/Brisbane"));
container.i = container.odt.toInstant();
container.zi = ZoneId.of("Australia/Brisbane");

final JsonObject serialized = new JsonObject();
serialized.add("ld", new JsonPrimitive("1969-07-21"));
Expand All @@ -101,6 +104,7 @@ public void testDeserialisation() throws Exception
serialized.add("ot", new JsonPrimitive("12:56:00+10:00"));
serialized.add("zdt", new JsonPrimitive("1969-07-21T12:56:00+10:00[Australia/Brisbane]"));
serialized.add("i", new JsonPrimitive("1969-07-21T02:56:00Z"));
serialized.add("zi", new JsonPrimitive("Australia/Brisbane"));

final String jsonString = gson.toJson(serialized);
final Container deserialised = gson.fromJson(jsonString, Container.class);
Expand All @@ -112,6 +116,7 @@ public void testDeserialisation() throws Exception
assertThat(deserialised.ot, is(container.ot));
assertThat(deserialised.zdt, is(container.zdt));
assertThat(deserialised.i, is(container.i));
assertThat(deserialised.zi, is(container.zi));
}

/**
Expand All @@ -126,5 +131,6 @@ private static class Container
private OffsetTime ot;
private ZonedDateTime zdt;
private Instant i;
private ZoneId zi;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright 2014 Greg Kopff
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.fatboyindustrial.gsonjavatime;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import org.junit.Test;
import org.junit.Rule;
import org.junit.rules.ExpectedException;

import java.lang.reflect.Type;
import java.time.ZoneId;
import java.time.DateTimeException;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;

/**
* Tests for {@link ZoneIdConverter}.
*/
public class ZoneIdConverterTest {

/** The specific genericized type for {@code ZoneId}. */
private static final Type ZONE_ID_TYPE = new TypeToken<ZoneId>(){}.getType();
@Rule
public ExpectedException exception = ExpectedException.none();

/**
* Tests that serialising to JSON works.
*/
@Test
public void testSerialisation() throws Exception
{
final Gson gson = registerZoneId(new GsonBuilder()).create();

final ZoneId zoneId = ZoneId.of("Australia/Brisbane");
final String json= gson.toJson(zoneId, ZoneId.class);
assertThat(json, is("\"Australia/Brisbane\""));
}

/**
* Tests that deserialising from JSON works.
*/
@Test
public void testDeserialisation() throws Exception
{
final Gson gson = registerZoneId(new GsonBuilder()).create();

final String json = "\"Australia/Brisbane\"";
final ZoneId zoneId = gson.fromJson(json, ZoneId.class);

assertThat(zoneId, is(ZoneId.of("Australia/Brisbane")));
}

/**
* Tests that deserialising from JSON works with an empty value.
*/
@Test
public void testDeserialisationWithEmptyValue() throws Exception
{
final Gson gson = registerZoneId(new GsonBuilder()).create();

final String json = "\"\"";
final ZoneId zoneId = gson.fromJson(json, ZoneId.class);

assertNull(zoneId);
}

/**
* Tests that deserialising from JSON works with a whitespace.
*/
@Test
public void testDeserialisationWithWhitespace() throws Exception
{
exception.expect(DateTimeException.class);
exception.expectMessage("Invalid ID for ZoneOffset, invalid format: ");

final Gson gson = registerZoneId(new GsonBuilder()).create();

final String json = "\" \"";
final ZoneId zoneId = gson.fromJson(json, ZoneId.class);
}

/**
* Registers the {@link ZoneIdConverter} converter.
* @param builder The GSON builder to register the converter with.
* @return A reference to {@code builder}.
*/
private static GsonBuilder registerZoneId(GsonBuilder builder)
{
builder.registerTypeAdapter(ZONE_ID_TYPE, new ZoneIdConverter());

return builder;
}
}

0 comments on commit 2fb0fbb

Please sign in to comment.