Repository: kyoripowered/adventure
Issue: Expected BOOLEAN but was STRING at path $.underlined

Copied from Discord, but of course if you need more information I'm happy to provide.

Hello! Geyser just updated from 4.8.0 to 4.9.2 and we've got what appears to be a brand new error! yey
```
[09:47:22] [defaultEventLoopGroup-3-10/WARN] [Geyser-BungeeCord]: Downstream packet error! java.lang.IllegalStateException: Expected BOOLEAN but was STRING at path $.bold
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BOOLEAN but was STRING at path $.bold
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at com.google.gson.Gson.fromJson(Gson.java:944)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at com.google.gson.Gson.fromJson(Gson.java:1003)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at com.google.gson.Gson.fromJson(Gson.java:975)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at org.geysermc.platform.bungeecord.shaded.kyori.adventure.text.serializer.gson.ComponentSerializerImpl.read(ComponentSerializerImpl.java:214)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at org.geysermc.platform.bungeecord.shaded.kyori.adventure.text.serializer.gson.ComponentSerializerImpl.read(ComponentSerializerImpl.java:56)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at com.google.gson.TypeAdapter$1.read(TypeAdapter.java:199)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at com.google.gson.Gson.fromJson(Gson.java:932)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at org.geysermc.platform.bungeecord.shaded.kyori.adventure.text.serializer.gson.ComponentSerializerImpl.read(ComponentSerializerImpl.java:173)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at org.geysermc.platform.bungeecord.shaded.kyori.adventure.text.serializer.gson.ComponentSerializerImpl.read(ComponentSerializerImpl.java:56)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at com.google.gson.TypeAdapter$1.read(TypeAdapter.java:199)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at com.google.gson.Gson.fromJson(Gson.java:932)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at com.google.gson.Gson.fromJson(Gson.java:897)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at com.google.gson.Gson.fromJson(Gson.java:846)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at com.google.gson.Gson.fromJson(Gson.java:817)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at org.geysermc.platform.bungeecord.shaded.kyori.adventure.text.serializer.gson.GsonComponentSerializerImpl.deserialize(GsonComponentSerializerImpl.java:84)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at org.geysermc.platform.bungeecord.shaded.kyori.adventure.text.serializer.gson.GsonComponentSerializerImpl.deserialize(GsonComponentSerializerImpl.java:37)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at com.github.steveice10.mc.protocol.packet.ingame.server.ServerPlayerListEntryPacket.read(ServerPlayerListEntryPacket.java:93)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at com.github.steveice10.packetlib.tcp.TcpPacketCodec.decode(TcpPacketCodec.java:59)
[09:47:22] [defaultEventLoopGroup-3-10/ERROR]:     at io.netty.handler.codec.ByteToMessageCodec$1.decode(ByteToMessageCodec.java:42)
```
I *believe* this is an example suspect string: `{"text":"","extra":[{"text":"lobby","color":"yellow","underlined":"true"},{"text":" (1):","color":"white","italic":"true"}]}` though I get `Expected BOOLEAN but was STRING at path $.underlined` with that.



Changed files:
text-serializer-gson/src/main/java/net/kyori/adventure/text/serializer/gson/StyleSerializer.java
text-serializer-gson/src/test/java/net/kyori/adventure/text/serializer/gson/StyleTest.java

diff --git a/text-serializer-gson/src/main/java/net/kyori/adventure/text/serializer/gson/StyleSerializer.java b/text-serializer-gson/src/main/java/net/kyori/adventure/text/serializer/gson/StyleSerializer.java
index 7293b0f4..cf0d317f 100644
--- a/text-serializer-gson/src/main/java/net/kyori/adventure/text/serializer/gson/StyleSerializer.java
+++ b/text-serializer-gson/src/main/java/net/kyori/adventure/text/serializer/gson/StyleSerializer.java
@@ -111,7 +111,7 @@ final class StyleSerializer extends TypeAdapter<Style> {
           style.decoration(color.decoration, TextDecoration.State.TRUE);
         }
       } else if (TextDecoration.NAMES.keys().contains(fieldName)) {
-        style.decoration(TextDecoration.NAMES.value(fieldName), in.nextBoolean());
+        style.decoration(TextDecoration.NAMES.value(fieldName), this.readBoolean(in));
       } else if (fieldName.equals(INSERTION)) {
         style.insertion(in.nextString());
       } else if (fieldName.equals(CLICK_EVENT)) {
@@ -177,6 +177,17 @@ final class StyleSerializer extends TypeAdapter<Style> {
     return style.build();
   }
 
+  private boolean readBoolean(final JsonReader in) throws IOException {
+    final JsonToken peek = in.peek();
+    if (peek == JsonToken.BOOLEAN) {
+      return in.nextBoolean();
+    } else if (peek == JsonToken.STRING || peek == JsonToken.NUMBER) {
+      return Boolean.parseBoolean(in.nextString());
+    } else {
+      throw new JsonParseException("Token of type " + peek + " cannot be interpreted as a boolean");
+    }
+  }
+
   private Object legacyHoverEventContents(final HoverEvent.Action<?> action, final Component rawValue) {
     if (action == HoverEvent.Action.SHOW_TEXT) {
       return rawValue; // Passthrough -- no serialization needed
diff --git a/text-serializer-gson/src/test/java/net/kyori/adventure/text/serializer/gson/StyleTest.java b/text-serializer-gson/src/test/java/net/kyori/adventure/text/serializer/gson/StyleTest.java
index 9d8147ce..ac9db8fd 100644
--- a/text-serializer-gson/src/test/java/net/kyori/adventure/text/serializer/gson/StyleTest.java
+++ b/text-serializer-gson/src/test/java/net/kyori/adventure/text/serializer/gson/StyleTest.java
@@ -24,6 +24,8 @@
 package net.kyori.adventure.text.serializer.gson;
 
 import com.google.gson.JsonElement;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonParseException;
 import java.util.UUID;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -39,7 +41,9 @@ import net.kyori.adventure.text.format.TextDecoration;
 import org.junit.jupiter.api.Test;
 
 import static com.google.common.truth.Truth.assertThat;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 @SuppressWarnings("CodeBlock2Expr")
@@ -87,6 +91,27 @@ class StyleTest extends GsonTest<Style> {
   @Test
   void testDecoration() {
     this.test(Style.style(TextDecoration.BOLD), object(json -> json.addProperty(name(TextDecoration.BOLD), true)));
+
+    Style s0 = GsonComponentSerializer.gson().serializer().fromJson(object(object -> {
+      object.addProperty(name(TextDecoration.BOLD), "true");
+    }), Style.class);
+    assertTrue(s0.hasDecoration(TextDecoration.BOLD));
+
+    s0 = GsonComponentSerializer.gson().serializer().fromJson(object(object -> {
+      object.addProperty(name(TextDecoration.BOLD), "false");
+    }), Style.class);
+    assertFalse(s0.hasDecoration(TextDecoration.BOLD));
+
+    s0 = GsonComponentSerializer.gson().serializer().fromJson(object(object -> {
+      object.addProperty(name(TextDecoration.BOLD), 1);
+    }), Style.class);
+    assertFalse(s0.hasDecoration(TextDecoration.BOLD));
+
+    assertThrows(JsonParseException.class, () -> {
+      GsonComponentSerializer.gson().serializer().fromJson(object(object -> {
+        object.add(name(TextDecoration.BOLD), JsonNull.INSTANCE);
+      }), Style.class);
+    });
   }
 
   @Test