diff --git a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/AdapterGenerator.kt b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/AdapterGenerator.kt index 1cfef3f..58d2bc4 100644 --- a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/AdapterGenerator.kt +++ b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/AdapterGenerator.kt @@ -125,11 +125,7 @@ internal class AdapterGenerator( "%T.of(%L)", JsonReader.Options::class.asTypeName(), nonTransientProperties - .map { - // We manually put in quotes because we know the jsonName is already escaped. - val whitespaceSafeName = it.jsonName.replace(" ", "ยท") - CodeBlock.of("\"$whitespaceSafeName\"") - } + .map { CodeBlock.of("%S", it.jsonName) } .joinToCode(", ") ) .build() @@ -495,7 +491,7 @@ internal class AdapterGenerator( result.addStatement("%N.beginObject()", writerParam) nonTransientProperties.forEach { property -> // We manually put in quotes because we know the jsonName is already escaped - result.addStatement("%N.name(\"%L\")", writerParam, property.jsonName) + result.addStatement("%N.name(%S)", writerParam, property.jsonName) result.addStatement("%N.toJson(%N, %N.%N)", nameAllocator[property.delegateKey], writerParam, valueParam, property.name) } diff --git a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/metadata.kt b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/metadata.kt index e2cfe52..b020492 100644 --- a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/metadata.kt +++ b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/metadata.kt @@ -48,6 +48,7 @@ import java.lang.annotation.RetentionPolicy import java.lang.annotation.Target import java.util.TreeSet import javax.annotation.processing.Messager +import javax.lang.model.element.AnnotationMirror import javax.lang.model.element.Element import javax.lang.model.element.ElementKind import javax.lang.model.element.TypeElement @@ -328,11 +329,13 @@ private fun List?.qualifiers(elements: Elements): Set?.jsonName(): String? { if (this == null) return null - return find { it.className == JSON }?.let { - it.members[0].toString().removePrefix("name = \"").removeSuffix("\"") + return find { it.className == JSON }?.let { annotation -> + val mirror = requireNotNull(annotation.tag()) { + "Could not get the annotation mirror from the annotation spec" + } + mirror.elementValues.entries.single { it.key.simpleName.contentEquals("name") }.value.value as String } } diff --git a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest.kt b/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest.kt index e491eba..a5d28c5 100644 --- a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest.kt +++ b/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest.kt @@ -87,6 +87,26 @@ class GeneratedAdaptersTest { @JsonClass(generateAdapter = true) data class JsonAnnotationWithDollarSign(@Json(name = "\$foo") val bar: String) + @Test + fun jsonAnnotationWithQuotationMark() { + val adapter = moshi.adapter() + + // Read + val json = """{"\"foo\"": "bar"}""" + + val instance = adapter.fromJson(json)!! + assertThat(instance.bar).isEqualTo("bar") + + // Write + val expectedJson = """{"\"foo\"":"baz"}""" + + assertThat(adapter.toJson( + JsonAnnotationWithQuotationMark("baz"))).isEqualTo(expectedJson) + } + + @JsonClass(generateAdapter = true) + data class JsonAnnotationWithQuotationMark(@Json(name = "\"foo\"") val bar: String) + @Test fun defaultValues() { val adapter = moshi.adapter()