From 37ffabc291f00ef0bba2b91446dc14205d7cd4b8 Mon Sep 17 00:00:00 2001 From: Zak Shearman <34372536+ZakShearman@users.noreply.github.com> Date: Sun, 1 Oct 2023 15:39:55 +0100 Subject: [PATCH] Parse null lists as empty lists instead --- .../adapter/NullListToEmptyFactory.java | 53 +++++++++++++++++++ .../configs/common/ConfigItem.java | 3 +- .../configs/gamemode/GameModeCollection.java | 2 + 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 java/src/main/java/dev/emortal/api/liveconfigparser/adapter/NullListToEmptyFactory.java diff --git a/java/src/main/java/dev/emortal/api/liveconfigparser/adapter/NullListToEmptyFactory.java b/java/src/main/java/dev/emortal/api/liveconfigparser/adapter/NullListToEmptyFactory.java new file mode 100644 index 0000000..0548fac --- /dev/null +++ b/java/src/main/java/dev/emortal/api/liveconfigparser/adapter/NullListToEmptyFactory.java @@ -0,0 +1,53 @@ +package dev.emortal.api.liveconfigparser.adapter; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public final class NullListToEmptyFactory implements TypeAdapterFactory { + public static final NullListToEmptyFactory INSTANCE = new NullListToEmptyFactory(); + + private NullListToEmptyFactory() { + } + + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + Class rawType = type.getRawType(); + + // Only handle List and ArrayList; let other factories handle different types + if (rawType != List.class && rawType != ArrayList.class) { + return null; + } + + // Delegate which handles deserialization of non-null values, and serialization + TypeAdapter delegate = gson.getDelegateAdapter(this, type); + return new TypeAdapter<>() { + @Override + public void write(JsonWriter out, T value) throws IOException { + delegate.write(out, value); + } + + @Override + public T read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + + // Safe due to check at beginning of `create` method + @SuppressWarnings("unchecked") + T t = (T) new ArrayList<>(); + return t; + } else { + return delegate.read(in); + } + } + }; + } +} diff --git a/java/src/main/java/dev/emortal/api/liveconfigparser/configs/common/ConfigItem.java b/java/src/main/java/dev/emortal/api/liveconfigparser/configs/common/ConfigItem.java index 97cdbb3..566328f 100644 --- a/java/src/main/java/dev/emortal/api/liveconfigparser/configs/common/ConfigItem.java +++ b/java/src/main/java/dev/emortal/api/liveconfigparser/configs/common/ConfigItem.java @@ -1,7 +1,8 @@ package dev.emortal.api.liveconfigparser.configs.common; -import java.util.List; import org.jetbrains.annotations.NotNull; +import java.util.List; + public record ConfigItem(@NotNull String material, int slot, @NotNull String name, @NotNull List lore) { } diff --git a/java/src/main/java/dev/emortal/api/liveconfigparser/configs/gamemode/GameModeCollection.java b/java/src/main/java/dev/emortal/api/liveconfigparser/configs/gamemode/GameModeCollection.java index e08c350..9e95ae2 100644 --- a/java/src/main/java/dev/emortal/api/liveconfigparser/configs/gamemode/GameModeCollection.java +++ b/java/src/main/java/dev/emortal/api/liveconfigparser/configs/gamemode/GameModeCollection.java @@ -3,6 +3,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import dev.emortal.api.liveconfigparser.adapter.DurationAdapter; +import dev.emortal.api.liveconfigparser.adapter.NullListToEmptyFactory; import dev.emortal.api.liveconfigparser.configs.ConfigCollection; import dev.emortal.api.liveconfigparser.parser.ConfigParser; import io.kubernetes.client.openapi.ApiClient; @@ -41,6 +42,7 @@ private GameModeCollection(@NotNull Path localPath) throws IOException { private static final class Parser implements ConfigParser { private static final Gson GSON = new GsonBuilder() .registerTypeAdapter(Duration.class, new DurationAdapter().nullSafe()) + .registerTypeAdapterFactory(NullListToEmptyFactory.INSTANCE) .create(); @Override