From c8fd0e4bc26cedf8436775ff89d2560979f69dac Mon Sep 17 00:00:00 2001 From: jwilson Date: Mon, 25 May 2015 07:35:08 -0700 Subject: [PATCH] Reject unrecognized enum constants with an exception. Also promote enum adapter to StandardJsonAdapters.java. --- .../com/squareup/moshi/EnumJsonAdapter.java | 62 ------------------- .../main/java/com/squareup/moshi/Moshi.java | 1 - .../squareup/moshi/StandardJsonAdapters.java | 26 ++++++++ .../squareup/moshi/EnumJsonAdapterTest.java | 48 -------------- .../java/com/squareup/moshi/MoshiTest.java | 32 ++++++++++ 5 files changed, 58 insertions(+), 111 deletions(-) delete mode 100644 moshi/src/main/java/com/squareup/moshi/EnumJsonAdapter.java delete mode 100644 moshi/src/test/java/com/squareup/moshi/EnumJsonAdapterTest.java diff --git a/moshi/src/main/java/com/squareup/moshi/EnumJsonAdapter.java b/moshi/src/main/java/com/squareup/moshi/EnumJsonAdapter.java deleted file mode 100644 index 2f12721..0000000 --- a/moshi/src/main/java/com/squareup/moshi/EnumJsonAdapter.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2014 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.moshi; - -import java.io.IOException; -import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Type; - -/** - * Convert Enum types to JSON string values - * - * @param Enum class to adapt - */ -final class EnumJsonAdapter> extends JsonAdapter { - public static final Factory FACTORY = new Factory() { - @Override public JsonAdapter create(Type type, AnnotatedElement annotations, - Moshi moshi) { - Class rawType = Types.getRawType(type); - if (Enum.class.isAssignableFrom(rawType)) { - //noinspection unchecked - Class enumType = (Class) rawType; - return new EnumJsonAdapter<>(enumType.getEnumConstants()).nullSafe(); - } - return null; - } - }; - - private final T[] values; - - private EnumJsonAdapter(T[] values) { - this.values = values; - } - - @Override - public T fromJson(JsonReader reader) throws IOException { - String name = reader.nextString(); - for (T value : values) { - if (value.name().equals(name)) { - return value; - } - } - return null; - } - - @Override - public void toJson(JsonWriter writer, T value) throws IOException { - writer.value(value.name()); - } -} diff --git a/moshi/src/main/java/com/squareup/moshi/Moshi.java b/moshi/src/main/java/com/squareup/moshi/Moshi.java index 9098f47..2973883 100644 --- a/moshi/src/main/java/com/squareup/moshi/Moshi.java +++ b/moshi/src/main/java/com/squareup/moshi/Moshi.java @@ -34,7 +34,6 @@ public final class Moshi { List factories = new ArrayList<>(); factories.addAll(builder.factories); factories.add(StandardJsonAdapters.FACTORY); - factories.add(EnumJsonAdapter.FACTORY); factories.add(CollectionJsonAdapter.FACTORY); factories.add(MapJsonAdapter.FACTORY); factories.add(ArrayJsonAdapter.FACTORY); diff --git a/moshi/src/main/java/com/squareup/moshi/StandardJsonAdapters.java b/moshi/src/main/java/com/squareup/moshi/StandardJsonAdapters.java index ad75957..8c645fc 100644 --- a/moshi/src/main/java/com/squareup/moshi/StandardJsonAdapters.java +++ b/moshi/src/main/java/com/squareup/moshi/StandardJsonAdapters.java @@ -18,6 +18,7 @@ package com.squareup.moshi; import java.io.IOException; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Type; +import java.util.Arrays; final class StandardJsonAdapters { public static final JsonAdapter.Factory FACTORY = new JsonAdapter.Factory() { @@ -39,6 +40,12 @@ final class StandardJsonAdapters { if (type == Long.class) return LONG_JSON_ADAPTER.nullSafe(); if (type == Short.class) return SHORT_JSON_ADAPTER.nullSafe(); if (type == String.class) return STRING_JSON_ADAPTER.nullSafe(); + + Class rawType = Types.getRawType(type); + if (rawType.isEnum()) { + //noinspection unchecked + return enumAdapter((Class) rawType).nullSafe(); + } return null; } }; @@ -160,4 +167,23 @@ final class StandardJsonAdapters { writer.value(value); } }; + + static > JsonAdapter enumAdapter(final Class enumType) { + return new JsonAdapter() { + @Override public T fromJson(JsonReader reader) throws IOException { + String name = reader.nextString(); + try { + return Enum.valueOf(enumType, name); + } catch (IllegalArgumentException e) { + throw new IllegalStateException("Expected one of " + + Arrays.toString(enumType.getEnumConstants()) + " but was " + name + " at path " + + reader.getPath()); + } + } + + @Override public void toJson(JsonWriter writer, T value) throws IOException { + writer.value(value.name()); + } + }; + } } diff --git a/moshi/src/test/java/com/squareup/moshi/EnumJsonAdapterTest.java b/moshi/src/test/java/com/squareup/moshi/EnumJsonAdapterTest.java deleted file mode 100644 index 4507e04..0000000 --- a/moshi/src/test/java/com/squareup/moshi/EnumJsonAdapterTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2014 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.moshi; - -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class EnumJsonAdapterTest { - private final Moshi moshi = new Moshi.Builder().build(); - - enum Roshambo { - ROCK, - PAPER, - SCISSORS - } - - @Test public void basics() throws Exception { - JsonAdapter adapter = moshi.adapter(Roshambo.class).lenient(); - assertThat(adapter.fromJson("\"ROCK\"")).isEqualTo(Roshambo.ROCK); - assertThat(adapter.toJson(Roshambo.PAPER)).isEqualTo("\"PAPER\""); - } - - @Test public void invalidInput() throws Exception { - JsonAdapter adapter = moshi.adapter(Roshambo.class).lenient(); - assertThat(adapter.fromJson("\"Lizard\"")).isNull(); - assertThat(adapter.fromJson("\"SPOCK\"")).isNull(); - } - - @Test public void nulls() throws Exception { - JsonAdapter adapter = moshi.adapter(Roshambo.class).lenient(); - assertThat(adapter.fromJson("null")).isNull(); - assertThat(adapter.toJson(null)).isEqualTo("null"); - } -} \ No newline at end of file diff --git a/moshi/src/test/java/com/squareup/moshi/MoshiTest.java b/moshi/src/test/java/com/squareup/moshi/MoshiTest.java index 42eb2ef..b589383 100644 --- a/moshi/src/test/java/com/squareup/moshi/MoshiTest.java +++ b/moshi/src/test/java/com/squareup/moshi/MoshiTest.java @@ -658,6 +658,32 @@ public final class MoshiTest { assertThat(adapter.fromJson("[2,3]")).containsExactly(2, 3); } + @Test public void enumAdapter() throws Exception { + Moshi moshi = new Moshi.Builder().build(); + JsonAdapter adapter = moshi.adapter(Roshambo.class).lenient(); + assertThat(adapter.fromJson("\"ROCK\"")).isEqualTo(Roshambo.ROCK); + assertThat(adapter.toJson(Roshambo.PAPER)).isEqualTo("\"PAPER\""); + } + + @Test public void invalidEnum() throws Exception { + Moshi moshi = new Moshi.Builder().build(); + JsonAdapter adapter = moshi.adapter(Roshambo.class).lenient(); + try { + adapter.fromJson("\"SPOCK\""); + fail(); + } catch (IllegalStateException expected) { + assertThat(expected.getMessage()) + .isEqualTo("Expected one of [ROCK, PAPER, SCISSORS] but was SPOCK at path $"); + } + } + + @Test public void nullEnum() throws Exception { + Moshi moshi = new Moshi.Builder().build(); + JsonAdapter adapter = moshi.adapter(Roshambo.class).lenient(); + assertThat(adapter.fromJson("null")).isNull(); + assertThat(adapter.toJson(null)).isEqualTo("null"); + } + static class Pizza { final int diameter; final boolean extraCheese; @@ -774,4 +800,10 @@ public final class MoshiTest { }; } } + + enum Roshambo { + ROCK, + PAPER, + SCISSORS + } }