From d01b1c8ba69fbc9d97d86566c3348d29482b1f03 Mon Sep 17 00:00:00 2001 From: Mikhail2048 Date: Sun, 4 Jun 2023 22:57:32 +0300 Subject: [PATCH] Allow trailing comma in lentient mode --- build.gradle.kts | 6 +-- .../com/squareup/moshi/ClassJsonAdapter.kt | 28 +++++++----- .../java/com/squareup/moshi/JsonUtf8Reader.kt | 3 +- .../com/squareup/moshi/JsonAdapterTest.java | 45 +++++++++++++++++++ .../squareup/moshi/JsonUtf8ReaderTest.java | 6 ++- 5 files changed, 69 insertions(+), 19 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index f10b09dcc..8d54a3db2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,10 +9,8 @@ import java.net.URL buildscript { dependencies { - val kotlinVersion = System.getenv("MOSHI_KOTLIN_VERSION") - ?: libs.versions.kotlin.get() - val kspVersion = System.getenv("MOSHI_KSP_VERSION") - ?: libs.versions.ksp.get() + val kotlinVersion = System.getenv("MOSHI_KOTLIN_VERSION") ?: libs.versions.kotlin.get() + val kspVersion = System.getenv("MOSHI_KSP_VERSION") ?: libs.versions.ksp.get() classpath(kotlin("gradle-plugin", version = kotlinVersion)) classpath("com.google.devtools.ksp:symbol-processing-gradle-plugin:$kspVersion") // https://github.com/melix/japicmp-gradle-plugin/issues/36 diff --git a/moshi/src/main/java/com/squareup/moshi/ClassJsonAdapter.kt b/moshi/src/main/java/com/squareup/moshi/ClassJsonAdapter.kt index 3ba9b4f43..132bba11e 100644 --- a/moshi/src/main/java/com/squareup/moshi/ClassJsonAdapter.kt +++ b/moshi/src/main/java/com/squareup/moshi/ClassJsonAdapter.kt @@ -55,15 +55,7 @@ internal class ClassJsonAdapter( private val options = JsonReader.Options.of(*fieldsMap.keys.toTypedArray()) override fun fromJson(reader: JsonReader): T { - val result: T = try { - classFactory.newInstance() - } catch (e: InstantiationException) { - throw RuntimeException(e) - } catch (e: InvocationTargetException) { - throw e.rethrowCause() - } catch (e: IllegalAccessException) { - throw AssertionError() - } + val instance: T = instanciateTargetClass() try { reader.beginObject() @@ -74,10 +66,22 @@ internal class ClassJsonAdapter( reader.skipValue() continue } - fieldsArray[index].read(reader, result) + fieldsArray[index].read(reader, instance) } reader.endObject() - return result + return instance + } catch (e: IllegalAccessException) { + throw AssertionError() + } + } + + private fun instanciateTargetClass(): T { + return try { + classFactory.newInstance() + } catch (e: InstantiationException) { + throw RuntimeException(e) + } catch (e: InvocationTargetException) { + throw e.rethrowCause() } catch (e: IllegalAccessException) { throw AssertionError() } @@ -96,7 +100,7 @@ internal class ClassJsonAdapter( } } - override fun toString() = "JsonAdapter($classFactory)" + override fun toString() = "ClassJsonAdapter($classFactory)" internal class FieldBinding(val name: String, val field: Field, val adapter: JsonAdapter) { fun read(reader: JsonReader, value: Any?) { diff --git a/moshi/src/main/java/com/squareup/moshi/JsonUtf8Reader.kt b/moshi/src/main/java/com/squareup/moshi/JsonUtf8Reader.kt index 75ec851d1..ebbd6b990 100644 --- a/moshi/src/main/java/com/squareup/moshi/JsonUtf8Reader.kt +++ b/moshi/src/main/java/com/squareup/moshi/JsonUtf8Reader.kt @@ -189,7 +189,8 @@ internal class JsonUtf8Reader : JsonReader { buffer.readByte() // consume the '}'. PEEKED_END_OBJECT } else { - throw syntaxError("Expected name") + checkLenient() + PEEKED_END_OBJECT } else -> { checkLenient() diff --git a/moshi/src/test/java/com/squareup/moshi/JsonAdapterTest.java b/moshi/src/test/java/com/squareup/moshi/JsonAdapterTest.java index c37042cab..5b8cf6acc 100644 --- a/moshi/src/test/java/com/squareup/moshi/JsonAdapterTest.java +++ b/moshi/src/test/java/com/squareup/moshi/JsonAdapterTest.java @@ -16,6 +16,7 @@ package com.squareup.moshi; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; @@ -26,6 +27,7 @@ import java.util.Locale; import java.util.Map; import javax.annotation.Nullable; +import org.intellij.lang.annotations.Language; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -338,4 +340,47 @@ public void nonNullDoesntDuplicate() { JsonAdapter adapter = new Moshi.Builder().build().adapter(Boolean.class).nonNull(); assertThat(adapter.nonNull()).isSameInstanceAs(adapter); } + + @Test + public void givenJsonWithTrailingComma_whenDeserializeInLenientMode_thenDeserializeSuccessfully() + throws IOException { + JsonAdapter adapter = new Moshi.Builder().build().adapter(Ticket.class).lenient(); + @Language("JSON") + String json = "{ \"number\" : \"912392\", \"seat\": 1234, \"type\" : \"COMMON\", }"; + Ticket ticket = adapter.fromJson(json); + assertNotNull(ticket); + assertThat(ticket.getNumber()).isEqualTo("912392"); + assertThat(ticket.getSeat()).isEqualTo(1234); + assertThat(ticket.getType()).isEqualTo("COMMON"); + } + + static class Ticket { + private String number; + private Integer seat; + private String type; + + public String getNumber() { + return number; + } + + public void setNumber(String number) { + this.number = number; + } + + public Integer getSeat() { + return seat; + } + + public void setSeat(Integer seat) { + this.seat = seat; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + } } diff --git a/moshi/src/test/java/com/squareup/moshi/JsonUtf8ReaderTest.java b/moshi/src/test/java/com/squareup/moshi/JsonUtf8ReaderTest.java index 551f3b73a..f331a6ca8 100644 --- a/moshi/src/test/java/com/squareup/moshi/JsonUtf8ReaderTest.java +++ b/moshi/src/test/java/com/squareup/moshi/JsonUtf8ReaderTest.java @@ -39,6 +39,7 @@ import okio.ForwardingSource; import okio.Okio; import okio.Source; +import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -1268,9 +1269,10 @@ public void lenientExtraCommasInMaps() throws IOException { assertThat(reader.nextName()).isEqualTo("a"); assertThat(reader.nextString()).isEqualTo("b"); try { - reader.peek(); + JsonReader.Token peek = reader.peek(); + Assert.assertEquals(JsonReader.Token.END_OBJECT, peek); + } catch (JsonEncodingException unexpected) { fail(); - } catch (JsonEncodingException expected) { } }