diff --git a/moshi/japicmp/build.gradle.kts b/moshi/japicmp/build.gradle.kts index a584185..213eff6 100644 --- a/moshi/japicmp/build.gradle.kts +++ b/moshi/japicmp/build.gradle.kts @@ -28,7 +28,8 @@ val japicmp = tasks.register("japicmp") { classExcludes = listOf( "com.squareup.moshi.internal.NonNullJsonAdapter", // Internal. "com.squareup.moshi.internal.NullSafeJsonAdapter", // Internal. - "com.squareup.moshi.internal.Util" // Internal. + "com.squareup.moshi.internal.Util", // Internal. + "com.squareup.moshi.StandardJsonAdapters" // Package-private ) methodExcludes = listOf( "com.squareup.moshi.JsonAdapter#indent(java.lang.String)" // Was unintentionally open before diff --git a/moshi/src/main/java/com/squareup/moshi/Moshi.kt b/moshi/src/main/java/com/squareup/moshi/Moshi.kt index c2044f8..0d6aeff 100644 --- a/moshi/src/main/java/com/squareup/moshi/Moshi.kt +++ b/moshi/src/main/java/com/squareup/moshi/Moshi.kt @@ -329,7 +329,7 @@ public class Moshi internal constructor(builder: Builder) { internal companion object { @JvmField val BUILT_IN_FACTORIES: List = buildList(6) { - add(StandardJsonAdapters.FACTORY) + add(StandardJsonAdapters) add(CollectionJsonAdapter.Factory) add(MapJsonAdapter.FACTORY) 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 deleted file mode 100644 index 05dc096..0000000 --- a/moshi/src/main/java/com/squareup/moshi/StandardJsonAdapters.java +++ /dev/null @@ -1,396 +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 - * - * https://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 static com.squareup.moshi.internal.Util.generatedAdapter; - -import com.squareup.moshi.internal.Util; -import java.io.IOException; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -final class StandardJsonAdapters { - private StandardJsonAdapters() {} - - public static final JsonAdapter.Factory FACTORY = - new JsonAdapter.Factory() { - @Override - public JsonAdapter create( - Type type, Set annotations, Moshi moshi) { - if (!annotations.isEmpty()) return null; - if (type == boolean.class) return BOOLEAN_JSON_ADAPTER; - if (type == byte.class) return BYTE_JSON_ADAPTER; - if (type == char.class) return CHARACTER_JSON_ADAPTER; - if (type == double.class) return DOUBLE_JSON_ADAPTER; - if (type == float.class) return FLOAT_JSON_ADAPTER; - if (type == int.class) return INTEGER_JSON_ADAPTER; - if (type == long.class) return LONG_JSON_ADAPTER; - if (type == short.class) return SHORT_JSON_ADAPTER; - if (type == Boolean.class) return BOOLEAN_JSON_ADAPTER.nullSafe(); - if (type == Byte.class) return BYTE_JSON_ADAPTER.nullSafe(); - if (type == Character.class) return CHARACTER_JSON_ADAPTER.nullSafe(); - if (type == Double.class) return DOUBLE_JSON_ADAPTER.nullSafe(); - if (type == Float.class) return FLOAT_JSON_ADAPTER.nullSafe(); - if (type == Integer.class) return INTEGER_JSON_ADAPTER.nullSafe(); - 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(); - if (type == Object.class) return new ObjectJsonAdapter(moshi).nullSafe(); - - Class rawType = Types.getRawType(type); - - @Nullable JsonAdapter generatedAdapter = generatedAdapter(moshi, type, rawType); - if (generatedAdapter != null) { - return generatedAdapter; - } - - if (rawType.isEnum()) { - //noinspection unchecked - return new EnumJsonAdapter<>((Class) rawType).nullSafe(); - } - return null; - } - }; - - private static final String ERROR_FORMAT = "Expected %s but was %s at path %s"; - - static int rangeCheckNextInt(JsonReader reader, String typeMessage, int min, int max) - throws IOException { - int value = reader.nextInt(); - if (value < min || value > max) { - throw new JsonDataException( - String.format(ERROR_FORMAT, typeMessage, value, reader.getPath())); - } - return value; - } - - static final JsonAdapter BOOLEAN_JSON_ADAPTER = - new JsonAdapter() { - @Override - public Boolean fromJson(JsonReader reader) throws IOException { - return reader.nextBoolean(); - } - - @Override - public void toJson(JsonWriter writer, Boolean value) throws IOException { - writer.value(value.booleanValue()); - } - - @Override - public String toString() { - return "JsonAdapter(Boolean)"; - } - }; - - static final JsonAdapter BYTE_JSON_ADAPTER = - new JsonAdapter() { - @Override - public Byte fromJson(JsonReader reader) throws IOException { - return (byte) rangeCheckNextInt(reader, "a byte", Byte.MIN_VALUE, 0xff); - } - - @Override - public void toJson(JsonWriter writer, Byte value) throws IOException { - writer.value(value.intValue() & 0xff); - } - - @Override - public String toString() { - return "JsonAdapter(Byte)"; - } - }; - - static final JsonAdapter CHARACTER_JSON_ADAPTER = - new JsonAdapter() { - @Override - public Character fromJson(JsonReader reader) throws IOException { - String value = reader.nextString(); - if (value.length() > 1) { - throw new JsonDataException( - String.format(ERROR_FORMAT, "a char", '"' + value + '"', reader.getPath())); - } - return value.charAt(0); - } - - @Override - public void toJson(JsonWriter writer, Character value) throws IOException { - writer.value(value.toString()); - } - - @Override - public String toString() { - return "JsonAdapter(Character)"; - } - }; - - static final JsonAdapter DOUBLE_JSON_ADAPTER = - new JsonAdapter() { - @Override - public Double fromJson(JsonReader reader) throws IOException { - return reader.nextDouble(); - } - - @Override - public void toJson(JsonWriter writer, Double value) throws IOException { - writer.value(value.doubleValue()); - } - - @Override - public String toString() { - return "JsonAdapter(Double)"; - } - }; - - static final JsonAdapter FLOAT_JSON_ADAPTER = - new JsonAdapter() { - @Override - public Float fromJson(JsonReader reader) throws IOException { - float value = (float) reader.nextDouble(); - // Double check for infinity after float conversion; many doubles > Float.MAX - if (!reader.isLenient() && Float.isInfinite(value)) { - throw new JsonDataException( - "JSON forbids NaN and infinities: " + value + " at path " + reader.getPath()); - } - return value; - } - - @Override - public void toJson(JsonWriter writer, Float value) throws IOException { - // Manual null pointer check for the float.class adapter. - if (value == null) { - throw new NullPointerException(); - } - // Use the Number overload so we write out float precision instead of double precision. - writer.value(value); - } - - @Override - public String toString() { - return "JsonAdapter(Float)"; - } - }; - - static final JsonAdapter INTEGER_JSON_ADAPTER = - new JsonAdapter() { - @Override - public Integer fromJson(JsonReader reader) throws IOException { - return reader.nextInt(); - } - - @Override - public void toJson(JsonWriter writer, Integer value) throws IOException { - writer.value(value.intValue()); - } - - @Override - public String toString() { - return "JsonAdapter(Integer)"; - } - }; - - static final JsonAdapter LONG_JSON_ADAPTER = - new JsonAdapter() { - @Override - public Long fromJson(JsonReader reader) throws IOException { - return reader.nextLong(); - } - - @Override - public void toJson(JsonWriter writer, Long value) throws IOException { - writer.value(value.longValue()); - } - - @Override - public String toString() { - return "JsonAdapter(Long)"; - } - }; - - static final JsonAdapter SHORT_JSON_ADAPTER = - new JsonAdapter() { - @Override - public Short fromJson(JsonReader reader) throws IOException { - return (short) rangeCheckNextInt(reader, "a short", Short.MIN_VALUE, Short.MAX_VALUE); - } - - @Override - public void toJson(JsonWriter writer, Short value) throws IOException { - writer.value(value.intValue()); - } - - @Override - public String toString() { - return "JsonAdapter(Short)"; - } - }; - - static final JsonAdapter STRING_JSON_ADAPTER = - new JsonAdapter() { - @Override - public String fromJson(JsonReader reader) throws IOException { - return reader.nextString(); - } - - @Override - public void toJson(JsonWriter writer, String value) throws IOException { - writer.value(value); - } - - @Override - public String toString() { - return "JsonAdapter(String)"; - } - }; - - static final class EnumJsonAdapter> extends JsonAdapter { - private final Class enumType; - private final String[] nameStrings; - private final T[] constants; - private final JsonReader.Options options; - - EnumJsonAdapter(Class enumType) { - this.enumType = enumType; - try { - constants = enumType.getEnumConstants(); - nameStrings = new String[constants.length]; - for (int i = 0; i < constants.length; i++) { - T constant = constants[i]; - String constantName = constant.name(); - nameStrings[i] = Util.jsonName(enumType.getField(constantName), constantName); - } - options = JsonReader.Options.of(nameStrings); - } catch (NoSuchFieldException e) { - throw new AssertionError("Missing field in " + enumType.getName(), e); - } - } - - @Override - public T fromJson(JsonReader reader) throws IOException { - int index = reader.selectString(options); - if (index != -1) return constants[index]; - - // We can consume the string safely, we are terminating anyway. - String path = reader.getPath(); - String name = reader.nextString(); - throw new JsonDataException( - "Expected one of " - + Arrays.asList(nameStrings) - + " but was " - + name - + " at path " - + path); - } - - @Override - public void toJson(JsonWriter writer, T value) throws IOException { - writer.value(nameStrings[value.ordinal()]); - } - - @Override - public String toString() { - return "JsonAdapter(" + enumType.getName() + ")"; - } - } - - /** - * This adapter is used when the declared type is {@code java.lang.Object}. Typically the runtime - * type is something else, and when encoding JSON this delegates to the runtime type's adapter. - * For decoding (where there is no runtime type to inspect), this uses maps and lists. - * - *

This adapter needs a Moshi instance to look up the appropriate adapter for runtime types as - * they are encountered. - */ - static final class ObjectJsonAdapter extends JsonAdapter { - private final Moshi moshi; - private final JsonAdapter listJsonAdapter; - private final JsonAdapter mapAdapter; - private final JsonAdapter stringAdapter; - private final JsonAdapter doubleAdapter; - private final JsonAdapter booleanAdapter; - - ObjectJsonAdapter(Moshi moshi) { - this.moshi = moshi; - this.listJsonAdapter = moshi.adapter(List.class); - this.mapAdapter = moshi.adapter(Map.class); - this.stringAdapter = moshi.adapter(String.class); - this.doubleAdapter = moshi.adapter(Double.class); - this.booleanAdapter = moshi.adapter(Boolean.class); - } - - @Override - public Object fromJson(JsonReader reader) throws IOException { - switch (reader.peek()) { - case BEGIN_ARRAY: - return listJsonAdapter.fromJson(reader); - - case BEGIN_OBJECT: - return mapAdapter.fromJson(reader); - - case STRING: - return stringAdapter.fromJson(reader); - - case NUMBER: - return doubleAdapter.fromJson(reader); - - case BOOLEAN: - return booleanAdapter.fromJson(reader); - - case NULL: - return reader.nextNull(); - - default: - throw new IllegalStateException( - "Expected a value but was " + reader.peek() + " at path " + reader.getPath()); - } - } - - @Override - public void toJson(JsonWriter writer, Object value) throws IOException { - Class valueClass = value.getClass(); - if (valueClass == Object.class) { - // Don't recurse infinitely when the runtime type is also Object.class. - writer.beginObject(); - writer.endObject(); - } else { - moshi.adapter(toJsonType(valueClass), Util.NO_ANNOTATIONS).toJson(writer, value); - } - } - - /** - * Returns the type to look up a type adapter for when writing {@code value} to JSON. Without - * this, attempts to emit standard types like `LinkedHashMap` would fail because Moshi doesn't - * provide built-in adapters for implementation types. It knows how to write - * those types, but lacks a mechanism to read them because it doesn't know how to find the - * appropriate constructor. - */ - private Class toJsonType(Class valueClass) { - if (Map.class.isAssignableFrom(valueClass)) return Map.class; - if (Collection.class.isAssignableFrom(valueClass)) return Collection.class; - return valueClass; - } - - @Override - public String toString() { - return "JsonAdapter(Object)"; - } - } -} diff --git a/moshi/src/main/java/com/squareup/moshi/StandardJsonAdapters.kt b/moshi/src/main/java/com/squareup/moshi/StandardJsonAdapters.kt new file mode 100644 index 0000000..44e013c --- /dev/null +++ b/moshi/src/main/java/com/squareup/moshi/StandardJsonAdapters.kt @@ -0,0 +1,275 @@ +/* + * 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 + * + * https://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 com.squareup.moshi.internal.NO_ANNOTATIONS +import com.squareup.moshi.internal.generatedAdapter +import com.squareup.moshi.internal.jsonName +import com.squareup.moshi.internal.knownNotNull +import java.lang.reflect.Type + +internal object StandardJsonAdapters : JsonAdapter.Factory { + + private const val ERROR_FORMAT = "Expected %s but was %s at path %s" + + override fun create(type: Type, annotations: Set, moshi: Moshi): JsonAdapter<*>? { + if (annotations.isNotEmpty()) return null + if (type === Boolean::class.javaPrimitiveType) return BOOLEAN_JSON_ADAPTER + if (type === Byte::class.javaPrimitiveType) return BYTE_JSON_ADAPTER + if (type === Char::class.javaPrimitiveType) return CHARACTER_JSON_ADAPTER + if (type === Double::class.javaPrimitiveType) return DOUBLE_JSON_ADAPTER + if (type === Float::class.javaPrimitiveType) return FLOAT_JSON_ADAPTER + if (type === Int::class.javaPrimitiveType) return INTEGER_JSON_ADAPTER + if (type === Long::class.javaPrimitiveType) return LONG_JSON_ADAPTER + if (type === Short::class.javaPrimitiveType) return SHORT_JSON_ADAPTER + if (type === Boolean::class.javaObjectType) return BOOLEAN_JSON_ADAPTER.nullSafe() + if (type === Byte::class.javaObjectType) return BYTE_JSON_ADAPTER.nullSafe() + if (type === Char::class.javaObjectType) return CHARACTER_JSON_ADAPTER.nullSafe() + if (type === Double::class.javaObjectType) return DOUBLE_JSON_ADAPTER.nullSafe() + if (type === Float::class.javaObjectType) return FLOAT_JSON_ADAPTER.nullSafe() + if (type === Int::class.javaObjectType) return INTEGER_JSON_ADAPTER.nullSafe() + if (type === Long::class.javaObjectType) return LONG_JSON_ADAPTER.nullSafe() + if (type === Short::class.javaObjectType) return SHORT_JSON_ADAPTER.nullSafe() + if (type === String::class.java) return STRING_JSON_ADAPTER.nullSafe() + if (type === Any::class.java) return ObjectJsonAdapter(moshi).nullSafe() + val rawType = type.rawType + val generatedAdapter = moshi.generatedAdapter(type, rawType) + if (generatedAdapter != null) { + return generatedAdapter + } + return if (rawType.isEnum) { + @Suppress("UNCHECKED_CAST") + EnumJsonAdapter(rawType as Class>).nullSafe() + } else null + } + + fun rangeCheckNextInt(reader: JsonReader, typeMessage: String?, min: Int, max: Int): Int { + val value = reader.nextInt() + if (value !in min..max) { + throw JsonDataException(ERROR_FORMAT.format(typeMessage, value, reader.path)) + } + return value + } + + val BOOLEAN_JSON_ADAPTER: JsonAdapter = object : JsonAdapter() { + override fun fromJson(reader: JsonReader) = reader.nextBoolean() + + override fun toJson(writer: JsonWriter, value: Boolean?) { + writer.value(knownNotNull(value)) + } + + override fun toString() = "JsonAdapter(Boolean)" + } + + private val BYTE_JSON_ADAPTER: JsonAdapter = object : JsonAdapter() { + override fun fromJson(reader: JsonReader): Byte { + return rangeCheckNextInt(reader, "a byte", Byte.MIN_VALUE.toInt(), 0xff).toByte() + } + + override fun toJson(writer: JsonWriter, value: Byte?) { + writer.value((knownNotNull(value).toInt() and 0xff).toLong()) + } + + override fun toString() = "JsonAdapter(Byte)" + } + + private val CHARACTER_JSON_ADAPTER: JsonAdapter = object : JsonAdapter() { + override fun fromJson(reader: JsonReader): Char { + val value = reader.nextString() + if (value.length > 1) { + throw JsonDataException(ERROR_FORMAT.format("a char", "\"$value\"", reader.path)) + } + return value[0] + } + + override fun toJson(writer: JsonWriter, value: Char?) { + writer.value(knownNotNull(value).toString()) + } + + override fun toString() = "JsonAdapter(Character)" + } + + private val DOUBLE_JSON_ADAPTER: JsonAdapter = object : JsonAdapter() { + override fun fromJson(reader: JsonReader): Double { + return reader.nextDouble() + } + + override fun toJson(writer: JsonWriter, value: Double?) { + writer.value(knownNotNull(value).toDouble()) + } + + override fun toString() = "JsonAdapter(Double)" + } + + private val FLOAT_JSON_ADAPTER: JsonAdapter = object : JsonAdapter() { + override fun fromJson(reader: JsonReader): Float { + val value = reader.nextDouble().toFloat() + // Double check for infinity after float conversion; many doubles > Float.MAX + if (!reader.isLenient && value.isInfinite()) { + throw JsonDataException( + "JSON forbids NaN and infinities: $value at path ${reader.path}" + ) + } + return value + } + + override fun toJson(writer: JsonWriter, value: Float?) { + // Manual null pointer check for the float.class adapter. + if (value == null) { + throw NullPointerException() + } + // Use the Number overload so we write out float precision instead of double precision. + writer.value(value) + } + + override fun toString() = "JsonAdapter(Float)" + } + + private val INTEGER_JSON_ADAPTER: JsonAdapter = object : JsonAdapter() { + override fun fromJson(reader: JsonReader): Int { + return reader.nextInt() + } + + override fun toJson(writer: JsonWriter, value: Int?) { + writer.value(knownNotNull(value).toInt().toLong()) + } + + override fun toString() = "JsonAdapter(Integer)" + } + + private val LONG_JSON_ADAPTER: JsonAdapter = object : JsonAdapter() { + override fun fromJson(reader: JsonReader): Long { + return reader.nextLong() + } + + override fun toJson(writer: JsonWriter, value: Long?) { + writer.value(knownNotNull(value).toLong()) + } + + override fun toString() = "JsonAdapter(Long)" + } + + private val SHORT_JSON_ADAPTER: JsonAdapter = object : JsonAdapter() { + override fun fromJson(reader: JsonReader): Short { + return rangeCheckNextInt(reader, "a short", Short.MIN_VALUE.toInt(), Short.MAX_VALUE.toInt()).toShort() + } + + override fun toJson(writer: JsonWriter, value: Short?) { + writer.value(knownNotNull(value).toInt().toLong()) + } + + override fun toString() = "JsonAdapter(Short)" + } + + private val STRING_JSON_ADAPTER: JsonAdapter = object : JsonAdapter() { + override fun fromJson(reader: JsonReader): String? { + return reader.nextString() + } + + override fun toJson(writer: JsonWriter, value: String?) { + writer.value(value) + } + + override fun toString() = "JsonAdapter(String)" + } + + internal class EnumJsonAdapter>(private val enumType: Class) : JsonAdapter() { + private val constants: Array = enumType.enumConstants + private val nameStrings: Array = Array(constants.size) { i -> + val constant = constants[i] + val constantName = constant.name + try { + enumType.getField(constantName).jsonName(constantName) + } catch (e: NoSuchFieldException) { + throw AssertionError("Missing field in ${enumType.name}", e) + } + } + private var options: JsonReader.Options = JsonReader.Options.of(*nameStrings) + + override fun fromJson(reader: JsonReader): T { + val index = reader.selectString(options) + if (index != -1) return constants[index] + + // We can consume the string safely, we are terminating anyway. + val path = reader.path + val name = reader.nextString() + throw JsonDataException( + "Expected one of ${nameStrings.toList()} but was $name at path $path" + ) + } + + override fun toJson(writer: JsonWriter, value: T?) { + writer.value(nameStrings[knownNotNull(value).ordinal]) + } + + override fun toString() = "JsonAdapter(${enumType.name})" + } + + /** + * This adapter is used when the declared type is [Any]. Typically the runtime + * type is something else, and when encoding JSON this delegates to the runtime type's adapter. + * For decoding (where there is no runtime type to inspect), this uses maps and lists. + * + * This adapter needs a Moshi instance to look up the appropriate adapter for runtime types as + * they are encountered. + */ + internal class ObjectJsonAdapter(private val moshi: Moshi) : JsonAdapter() { + private val listJsonAdapter: JsonAdapter> = moshi.adapter(List::class.java) + private val mapAdapter: JsonAdapter> = moshi.adapter(Map::class.java) + private val stringAdapter: JsonAdapter = moshi.adapter(String::class.java) + private val doubleAdapter: JsonAdapter = moshi.adapter(Double::class.java) + private val booleanAdapter: JsonAdapter = moshi.adapter(Boolean::class.java) + + override fun fromJson(reader: JsonReader): Any? { + return when (reader.peek()) { + JsonReader.Token.BEGIN_ARRAY -> listJsonAdapter.fromJson(reader) + JsonReader.Token.BEGIN_OBJECT -> mapAdapter.fromJson(reader) + JsonReader.Token.STRING -> stringAdapter.fromJson(reader) + JsonReader.Token.NUMBER -> doubleAdapter.fromJson(reader) + JsonReader.Token.BOOLEAN -> booleanAdapter.fromJson(reader) + JsonReader.Token.NULL -> reader.nextNull() + else -> throw IllegalStateException( + "Expected a value but was ${reader.peek()} at path ${reader.path}" + ) + } + } + + override fun toJson(writer: JsonWriter, value: Any?) { + val valueClass: Class<*> = knownNotNull(value).javaClass + if (valueClass == Any::class.java) { + // Don't recurse infinitely when the runtime type is also Object.class. + writer.beginObject() + writer.endObject() + } else { + moshi.adapter(toJsonType(valueClass), NO_ANNOTATIONS).toJson(writer, value) + } + } + + /** + * Returns the type to look up a type adapter for when writing `value` to JSON. Without + * this, attempts to emit standard types like `LinkedHashMap` would fail because Moshi doesn't + * provide built-in adapters for implementation types. It knows how to **write** + * those types, but lacks a mechanism to read them because it doesn't know how to find the + * appropriate constructor. + */ + private fun toJsonType(valueClass: Class<*>): Class<*> { + if (Map::class.java.isAssignableFrom(valueClass)) return Map::class.java + return if (Collection::class.java.isAssignableFrom(valueClass)) Collection::class.java else valueClass + } + + override fun toString() = "JsonAdapter(Object)" + } +} diff --git a/moshi/src/test/java/com/squareup/moshi/MoshiTest.java b/moshi/src/test/java/com/squareup/moshi/MoshiTest.java index ca7016d..e79c06a 100644 --- a/moshi/src/test/java/com/squareup/moshi/MoshiTest.java +++ b/moshi/src/test/java/com/squareup/moshi/MoshiTest.java @@ -1160,7 +1160,10 @@ public final class MoshiTest { public void qualifierWithElementsMayNotBeDirectlyRegistered() throws IOException { try { new Moshi.Builder() - .add(Boolean.class, Localized.class, StandardJsonAdapters.BOOLEAN_JSON_ADAPTER); + .add( + Boolean.class, + Localized.class, + StandardJsonAdapters.INSTANCE.getBOOLEAN_JSON_ADAPTER()); fail(); } catch (IllegalArgumentException expected) { assertThat(expected)