diff --git a/commons-gson/build.gradle b/commons-gson/build.gradle index 93bc9c6..32cfa98 100644 --- a/commons-gson/build.gradle +++ b/commons-gson/build.gradle @@ -3,12 +3,13 @@ plugins { } dependencies { - shadow implementation('io.gitlab.jfronny:gson:+') + shadow implementation('io.gitlab.jfronny:gson:2.9.1-20220517.194826-5') } shadowJar { configurations = [ project.configurations.shadow ] archiveClassifier = '' + relocate 'com.google.gson', 'io.gitlab.jfronny.gson' } publishing { diff --git a/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/GsonHolder.java b/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/GsonHolder.java index bf1e796..437e2aa 100644 --- a/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/GsonHolder.java +++ b/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/GsonHolder.java @@ -1,40 +1,22 @@ package io.gitlab.jfronny.commons.serialize.gson; -import io.gitlab.jfronny.commons.ComparableVersion; -import io.gitlab.jfronny.commons.serialize.Serializer; -import io.gitlab.jfronny.commons.serialize.SerializerHolder; -import io.gitlab.jfronny.gson.*; +import com.google.gson.*; -import java.io.Reader; -import java.lang.reflect.Modifier; -import java.lang.reflect.Type; -import java.util.function.Consumer; +import java.lang.reflect.*; +import java.util.function.*; /** * Holds a common instance of the Gson object. * Supports registering type adapters/etc. as needed */ +@Deprecated(forRemoval = true) public class GsonHolder { - private static final GsonBuilder builder = new GsonBuilder() - .registerTypeAdapter(ComparableVersion.class, new ComparableVersionAdapter()) - .excludeFieldsWithModifiers(Modifier.TRANSIENT) - .excludeFieldsWithModifiers(Modifier.PRIVATE) - .setExclusionStrategies(new GsonIgnoreExclusionStrategy()) - .setPrettyPrinting(); - - private static boolean clean = false; - private static Gson gson; - /** * Get the current gson instance or build it if needed * @return The Gson instance */ public static Gson getGson() { - if (!clean) { - gson = builder.create(); - clean = true; - } - return gson; + return io.gitlab.jfronny.commons.serialize.gson.api.GsonHolder.getGson(); } /** @@ -43,8 +25,7 @@ public class GsonHolder { * @param typeAdapter The adapter type */ public static void registerTypeAdapter(Type type, Object typeAdapter) { - builder.registerTypeAdapter(type, typeAdapter); - clean = false; + io.gitlab.jfronny.commons.serialize.gson.api.GsonHolder.registerTypeAdapter(type, typeAdapter); } /** @@ -52,8 +33,7 @@ public class GsonHolder { * @param factory The factory to register */ public static void registerTypeAdapterFactory(TypeAdapterFactory factory) { - builder.registerTypeAdapterFactory(factory); - clean = false; + io.gitlab.jfronny.commons.serialize.gson.api.GsonHolder.registerTypeAdapterFactory(factory); } /** @@ -61,42 +41,13 @@ public class GsonHolder { * @param func The function to run */ public static void modifyBuilder(Consumer func) { - func.accept(builder); - clean = false; + io.gitlab.jfronny.commons.serialize.gson.api.GsonHolder.modifyBuilder(func); } /** * Register this in {@code SerializerHolder} */ public static void register() { - SerializerHolder.setInstance(new Serializer() { - @Override - public String serialize(Object o) { - return getGson().toJson(o); - } - - @Override - public T deserialize(Reader source, Type typeOfT) throws SerializeException { - try { - return getGson().fromJson(source, typeOfT); - } catch (JsonIOException | JsonSyntaxException e) { - throw new SerializeException(e); - } - } - - @Override - public T deserialize(String source, Type typeOfT) throws SerializeException { - try { - return getGson().fromJson(source, typeOfT); - } catch (JsonIOException | JsonSyntaxException e) { - throw new SerializeException(e); - } - } - - @Override - public String getFormatMime() { - return "application/json"; - } - }); + io.gitlab.jfronny.commons.serialize.gson.api.GsonHolder.register(); } } diff --git a/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/GsonIgnore.java b/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/GsonIgnore.java index 6c91307..1853924 100644 --- a/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/GsonIgnore.java +++ b/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/GsonIgnore.java @@ -9,6 +9,7 @@ import java.lang.annotation.Target; * Mark a class/field to be ignored by Gson. * May be used for metadata in serialized classes */ +@Deprecated(forRemoval = true) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.TYPE}) public @interface GsonIgnore { diff --git a/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/GsonIgnoreExclusionStrategy.java b/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/GsonIgnoreExclusionStrategy.java deleted file mode 100644 index 7718a19..0000000 --- a/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/GsonIgnoreExclusionStrategy.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.gitlab.jfronny.commons.serialize.gson; - -import io.gitlab.jfronny.gson.ExclusionStrategy; -import io.gitlab.jfronny.gson.FieldAttributes; - -/** - * An exclusion strategy that ignores fields with the GsonIgnore attribute - */ -public class GsonIgnoreExclusionStrategy implements ExclusionStrategy { - @Override - public boolean shouldSkipClass(Class clazz) { - return clazz.isAnnotationPresent(GsonIgnore.class); - } - - @Override - public boolean shouldSkipField(FieldAttributes f) { - return f.getAnnotation(GsonIgnore.class) != null - || f.getDeclaringClass().isAnnotationPresent(GsonIgnore.class); - } -} diff --git a/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/api/GsonHolder.java b/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/api/GsonHolder.java new file mode 100644 index 0000000..ad93ff2 --- /dev/null +++ b/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/api/GsonHolder.java @@ -0,0 +1,102 @@ +package io.gitlab.jfronny.commons.serialize.gson.api; + +import io.gitlab.jfronny.commons.*; +import io.gitlab.jfronny.commons.serialize.*; +import io.gitlab.jfronny.commons.serialize.gson.impl.*; +import com.google.gson.*; + +import java.io.*; +import java.lang.reflect.*; +import java.util.function.*; + +/** + * Holds a common instance of the Gson object. + * Supports registering type adapters/etc. as needed + */ +public class GsonHolder { + private static final GsonBuilder builder = new GsonBuilder() + .registerTypeAdapter(ComparableVersion.class, new ComparableVersionAdapter()) + .excludeFieldsWithModifiers(Modifier.TRANSIENT) + .excludeFieldsWithModifiers(Modifier.PRIVATE) + .setExclusionStrategies(new GsonIgnoreExclusionStrategy()) + .setLenient() + .setPrettyPrinting(); + + private static boolean clean = false; + private static Gson gson; + + /** + * Get the current gson instance or build it if needed + * @return The Gson instance + */ + public static Gson getGson() { + if (!clean) { + gson = builder.create(); + clean = true; + } + return gson; + } + + /** + * Register a type adapter and mark the gson instance as unclean + * @param type The type for which to register the adapter + * @param typeAdapter The adapter type + */ + public static void registerTypeAdapter(Type type, Object typeAdapter) { + builder.registerTypeAdapter(type, typeAdapter); + clean = false; + } + + /** + * Register a type adapter factory and mark the gson instance as unclean + * @param factory The factory to register + */ + public static void registerTypeAdapterFactory(TypeAdapterFactory factory) { + builder.registerTypeAdapterFactory(factory); + clean = false; + } + + /** + * Run a function on the builder for modifying it and mark the gson instance as unclean + * @param func The function to run + */ + public static void modifyBuilder(Consumer func) { + func.accept(builder); + clean = false; + } + + /** + * Register this in {@code SerializerHolder} + */ + public static void register() { + SerializerHolder.setInstance(new Serializer() { + @Override + public String serialize(Object o) { + return getGson().toJson(o); + } + + @Override + public T deserialize(Reader source, Type typeOfT) throws SerializeException { + try { + return getGson().fromJson(source, typeOfT); + } catch (JsonIOException | JsonSyntaxException e) { + throw new SerializeException(e); + } + } + + @Override + public T deserialize(String source, Type typeOfT) throws SerializeException { + try { + return getGson().fromJson(source, typeOfT); + } catch (JsonIOException | JsonSyntaxException e) { + throw new SerializeException(e); + } + } + + @Override + public String getFormatMime() { + return "application/json"; + } + }); + } +} diff --git a/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/api/Ignore.java b/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/api/Ignore.java new file mode 100644 index 0000000..f3b40db --- /dev/null +++ b/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/api/Ignore.java @@ -0,0 +1,12 @@ +package io.gitlab.jfronny.commons.serialize.gson.api; + +import java.lang.annotation.*; + +/** + * Mark a class/field to be ignored by Gson. + * May be used for metadata in serialized classes + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.TYPE}) +public @interface Ignore { +} diff --git a/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/ComparableVersionAdapter.java b/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/impl/ComparableVersionAdapter.java similarity index 91% rename from commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/ComparableVersionAdapter.java rename to commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/impl/ComparableVersionAdapter.java index 550a5eb..8ce6d82 100644 --- a/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/ComparableVersionAdapter.java +++ b/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/impl/ComparableVersionAdapter.java @@ -1,7 +1,7 @@ -package io.gitlab.jfronny.commons.serialize.gson; +package io.gitlab.jfronny.commons.serialize.gson.impl; import io.gitlab.jfronny.commons.ComparableVersion; -import io.gitlab.jfronny.gson.*; +import com.google.gson.*; import java.lang.reflect.Type; diff --git a/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/impl/GsonIgnoreExclusionStrategy.java b/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/impl/GsonIgnoreExclusionStrategy.java new file mode 100644 index 0000000..21f3498 --- /dev/null +++ b/commons-gson/src/main/java/io/gitlab/jfronny/commons/serialize/gson/impl/GsonIgnoreExclusionStrategy.java @@ -0,0 +1,25 @@ +package io.gitlab.jfronny.commons.serialize.gson.impl; + +import io.gitlab.jfronny.commons.serialize.gson.*; +import io.gitlab.jfronny.commons.serialize.gson.api.*; +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; + +/** + * An exclusion strategy that ignores fields with the GsonIgnore attribute + */ +public class GsonIgnoreExclusionStrategy implements ExclusionStrategy { + @Override + public boolean shouldSkipClass(Class clazz) { + return clazz.isAnnotationPresent(GsonIgnore.class) + || clazz.isAnnotationPresent(Ignore.class); + } + + @Override + public boolean shouldSkipField(FieldAttributes f) { + return f.getAnnotation(GsonIgnore.class) != null + || f.getDeclaringClass().isAnnotationPresent(GsonIgnore.class) + || f.getAnnotation(Ignore.class) != null + || f.getDeclaringClass().isAnnotationPresent(Ignore.class); + } +} diff --git a/commons-gson/src/test/java/io/gitlab/jfronny/commons/test/GsonTest.java b/commons-gson/src/test/java/io/gitlab/jfronny/commons/test/GsonTest.java index 9894be9..1de5f26 100644 --- a/commons-gson/src/test/java/io/gitlab/jfronny/commons/test/GsonTest.java +++ b/commons-gson/src/test/java/io/gitlab/jfronny/commons/test/GsonTest.java @@ -1,11 +1,9 @@ package io.gitlab.jfronny.commons.test; -import io.gitlab.jfronny.commons.ComparableVersion; -import io.gitlab.jfronny.commons.serialize.SerializerHolder; -import io.gitlab.jfronny.commons.serialize.gson.GsonHolder; -import io.gitlab.jfronny.commons.serialize.gson.GsonIgnore; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; +import io.gitlab.jfronny.commons.*; +import io.gitlab.jfronny.commons.serialize.*; +import io.gitlab.jfronny.commons.serialize.gson.api.*; +import org.junit.jupiter.api.*; import static org.junit.jupiter.api.Assertions.*; @@ -40,14 +38,14 @@ public class GsonTest { public static class ExampleType { String id = "Yes"; - @GsonIgnore + @Ignore String other = "No"; Integer one = 1; ExampleTypeHidden type = new ExampleTypeHidden(); TransitiveHiddenType shown = new TransitiveHiddenType(); } - @GsonIgnore + @Ignore public static class ExampleTypeHidden { String someMetadata = "No"; }