Move the Kotlin code generator to the kotlin/ module

This commit is contained in:
Jesse Wilson
2018-05-14 12:25:25 -04:00
parent c5c4cac6c3
commit 9f69029ef0
22 changed files with 75 additions and 58 deletions

143
kotlin/tests/pom.xml Normal file
View File

@@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi-parent</artifactId>
<version>1.6.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>moshi-kotlin-tests</artifactId>
<dependencies>
<dependency>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>kapt</id>
<goals>
<goal>kapt</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/main/kotlin</sourceDir>
</sourceDirs>
<annotationProcessorPaths>
<annotationProcessorPath>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi-kotlin-codegen</artifactId>
<version>${project.version}</version>
</annotationProcessorPath>
</annotationProcessorPaths>
</configuration>
</execution>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/main/kotlin</sourceDir>
<sourceDir>src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-kapt</id>
<goals>
<goal>test-kapt</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/test/kotlin</sourceDir>
<sourceDir>src/test/java</sourceDir>
</sourceDirs>
<annotationProcessorPaths>
<annotationProcessorPath>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi-kotlin-codegen</artifactId>
<version>${project.version}</version>
</annotationProcessorPath>
</annotationProcessorPaths>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/test/kotlin</sourceDir>
<sourceDir>src/test/java</sourceDir>
<sourceDir>target/generated-sources/kapt/test</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<proc>none</proc>
<source>1.6</source>
<target>1.6</target>
</configuration>
<executions>
<!-- Replacing default-compile as it is treated specially by maven -->
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<!-- Replacing default-testCompile as it is treated specially by maven -->
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals> <goal>testCompile</goal> </goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,840 @@
/*
* Copyright (C) 2018 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.kotlin.codgen
import com.squareup.moshi.FromJson
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.squareup.moshi.JsonDataException
import com.squareup.moshi.JsonQualifier
import com.squareup.moshi.Moshi
import com.squareup.moshi.ToJson
import com.squareup.moshi.Types
import org.assertj.core.api.Assertions.assertThat
import org.intellij.lang.annotations.Language
import org.junit.Assert.fail
import org.junit.Ignore
import org.junit.Test
import java.util.Locale
class GeneratedAdaptersTest {
private val moshi = Moshi.Builder().build()
@Test
fun jsonAnnotation() {
val adapter = moshi.adapter(JsonAnnotation::class.java)
// Read
@Language("JSON")
val json = """{"foo": "bar"}"""
val instance = adapter.fromJson(json)!!
assertThat(instance.bar).isEqualTo("bar")
// Write
@Language("JSON")
val expectedJson = """{"foo":"baz"}"""
assertThat(adapter.toJson(JsonAnnotation("baz"))).isEqualTo(expectedJson)
}
@JsonClass(generateAdapter = true)
data class JsonAnnotation(@Json(name = "foo") val bar: String)
@Test
fun defaultValues() {
val adapter = moshi.adapter(DefaultValues::class.java)
// Read/write with default values
@Language("JSON")
val json = """{"foo":"fooString"}"""
val instance = adapter.fromJson(json)!!
assertThat(instance.foo).isEqualTo("fooString")
assertThat(instance.bar).isEqualTo("")
assertThat(instance.nullableBar).isNull()
assertThat(instance.bazList).apply {
isNotNull()
isEmpty()
}
@Language("JSON") val expected = """{"foo":"fooString","bar":"","bazList":[]}"""
assertThat(adapter.toJson(DefaultValues("fooString"))).isEqualTo(expected)
// Read/write with real values
@Language("JSON")
val json2 = """
{"foo":"fooString","bar":"barString","nullableBar":"bar","bazList":["baz"]}
""".trimIndent()
val instance2 = adapter.fromJson(json2)!!
assertThat(instance2.foo).isEqualTo("fooString")
assertThat(instance2.bar).isEqualTo("barString")
assertThat(instance2.nullableBar).isEqualTo("bar")
assertThat(instance2.bazList).containsExactly("baz")
assertThat(adapter.toJson(instance2)).isEqualTo(json2)
}
@JsonClass(generateAdapter = true)
data class DefaultValues(
val foo: String,
val bar: String = "",
val nullableBar: String? = null,
val bazList: List<String> = emptyList())
@Test
fun nullableArray() {
val adapter = moshi.adapter(NullableArray::class.java)
@Language("JSON")
val json = """{"data":[null,"why"]}"""
val instance = adapter.fromJson(json)!!
assertThat(instance.data).containsExactly(null, "why")
assertThat(adapter.toJson(instance)).isEqualTo(json)
}
@JsonClass(generateAdapter = true)
data class NullableArray(val data: Array<String?>)
@Test
fun primitiveArray() {
val adapter = moshi.adapter(PrimitiveArray::class.java)
@Language("JSON")
val json = """{"ints":[0,1]}"""
val instance = adapter.fromJson(json)!!
assertThat(instance.ints).containsExactly(0, 1)
assertThat(adapter.toJson(instance)).isEqualTo(json)
}
@JsonClass(generateAdapter = true)
data class PrimitiveArray(val ints: IntArray)
@Test
fun nullableTypes() {
val adapter = moshi.adapter(NullabeTypes::class.java)
@Language("JSON")
val json = """{"foo":"foo","nullableString":null}"""
@Language("JSON")
val invalidJson = """{"foo":null,"nullableString":null}"""
val instance = adapter.fromJson(json)!!
assertThat(instance.foo).isEqualTo("foo")
assertThat(instance.nullableString).isNull()
try {
adapter.fromJson(invalidJson)
fail("The invalid json should have failed!")
} catch (e: JsonDataException) {
assertThat(e).hasMessageContaining("foo")
}
}
@JsonClass(generateAdapter = true)
data class NullabeTypes(
val foo: String,
val nullableString: String?
)
@Test
fun collections() {
val adapter = moshi.adapter(SpecialCollections::class.java)
val specialCollections = SpecialCollections(
mutableListOf(),
mutableSetOf(),
mutableMapOf(),
emptyList(),
emptySet(),
emptyMap()
)
val json = adapter.toJson(specialCollections)
val newCollections = adapter.fromJson(json)
assertThat(newCollections).isEqualTo(specialCollections)
}
@JsonClass(generateAdapter = true)
data class SpecialCollections(
val mutableList: MutableList<String>,
val mutableSet: MutableSet<String>,
val mutableMap: MutableMap<String, String>,
val immutableList: List<String>,
val immutableSet: Set<String>,
val immutableMap: Map<String, String>
)
@Test
fun mutableProperties() {
val adapter = moshi.adapter(MutableProperties::class.java)
val mutableProperties = MutableProperties(
"immutableProperty",
"mutableProperty",
mutableListOf("immutableMutableList"),
mutableListOf("immutableImmutableList"),
mutableListOf("mutableMutableList"),
mutableListOf("mutableImmutableList"),
"immutableProperty",
"mutableProperty",
mutableListOf("immutableMutableList"),
mutableListOf("immutableImmutableList"),
mutableListOf("mutableMutableList"),
mutableListOf("mutableImmutableList")
)
val json = adapter.toJson(mutableProperties)
val newMutableProperties = adapter.fromJson(json)
assertThat(newMutableProperties).isEqualTo(mutableProperties)
}
@JsonClass(generateAdapter = true)
data class MutableProperties(
val immutableProperty: String,
var mutableProperty: String,
val immutableMutableList: MutableList<String>,
val immutableImmutableList: List<String>,
var mutableMutableList: MutableList<String>,
var mutableImmutableList: List<String>,
val nullableImmutableProperty: String?,
var nullableMutableProperty: String?,
val nullableImmutableMutableList: MutableList<String>?,
val nullableImmutableImmutableList: List<String>?,
var nullableMutableMutableList: MutableList<String>?,
var nullableMutableImmutableList: List<String>
)
@Test
fun nullableTypeParams() {
val adapter = moshi.adapter<NullableTypeParams<Int>>(
Types.newParameterizedType(NullableTypeParams::class.java, Int::class.javaObjectType))
val nullSerializing = adapter.serializeNulls()
val nullableTypeParams = NullableTypeParams<Int>(
listOf("foo", null, "bar"),
setOf("foo", null, "bar"),
mapOf("foo" to "bar", "baz" to null),
null,
1
)
val noNullsTypeParams = NullableTypeParams<Int>(
nullableTypeParams.nullableList,
nullableTypeParams.nullableSet,
nullableTypeParams.nullableMap.filterValues { it != null },
null,
1
)
val json = adapter.toJson(nullableTypeParams)
val newNullableTypeParams = adapter.fromJson(json)
assertThat(newNullableTypeParams).isEqualTo(noNullsTypeParams)
val nullSerializedJson = nullSerializing.toJson(nullableTypeParams)
val nullSerializedNullableTypeParams = adapter.fromJson(nullSerializedJson)
assertThat(nullSerializedNullableTypeParams).isEqualTo(nullableTypeParams)
}
@Test fun doNotGenerateAdapter() {
try {
Class.forName("${GeneratedAdaptersTest::class.java.name}_DoNotGenerateAdapterJsonAdapter")
fail("found a generated adapter for a type that shouldn't have one")
} catch (expected: ClassNotFoundException) {
}
}
@JsonClass(generateAdapter = false)
data class DoNotGenerateAdapter(val foo: String)
@Test fun constructorParameters() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(ConstructorParameters::class.java)
val encoded = ConstructorParameters(3, 5)
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""")
val decoded = jsonAdapter.fromJson("""{"a":4,"b":6}""")!!
assertThat(decoded.a).isEqualTo(4)
assertThat(decoded.b).isEqualTo(6)
}
@JsonClass(generateAdapter = true)
class ConstructorParameters(var a: Int, var b: Int)
@Test fun properties() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(Properties::class.java)
val encoded = Properties()
encoded.a = 3
encoded.b = 5
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""")
val decoded = jsonAdapter.fromJson("""{"a":3,"b":5}""")!!
assertThat(decoded.a).isEqualTo(3)
assertThat(decoded.b).isEqualTo(5)
}
@JsonClass(generateAdapter = true)
class Properties {
var a: Int = -1
var b: Int = -1
}
@Test fun constructorParametersAndProperties() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(ConstructorParametersAndProperties::class.java)
val encoded = ConstructorParametersAndProperties(3)
encoded.b = 5
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""")
val decoded = jsonAdapter.fromJson("""{"a":4,"b":6}""")!!
assertThat(decoded.a).isEqualTo(4)
assertThat(decoded.b).isEqualTo(6)
}
@JsonClass(generateAdapter = true)
class ConstructorParametersAndProperties(var a: Int) {
var b: Int = -1
}
@Test fun immutableConstructorParameters() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(ImmutableConstructorParameters::class.java)
val encoded = ImmutableConstructorParameters(3, 5)
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""")
val decoded = jsonAdapter.fromJson("""{"a":4,"b":6}""")!!
assertThat(decoded.a).isEqualTo(4)
assertThat(decoded.b).isEqualTo(6)
}
@JsonClass(generateAdapter = true)
class ImmutableConstructorParameters(val a: Int, val b: Int)
@Test fun immutableProperties() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(ImmutableProperties::class.java)
val encoded = ImmutableProperties(3, 5)
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""")
val decoded = jsonAdapter.fromJson("""{"a":3,"b":5}""")!!
assertThat(decoded.a).isEqualTo(3)
assertThat(decoded.b).isEqualTo(5)
}
@JsonClass(generateAdapter = true)
class ImmutableProperties(a: Int, b: Int) {
val a = a
val b = b
}
@Test fun constructorDefaults() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(ConstructorDefaultValues::class.java)
val encoded = ConstructorDefaultValues(3, 5)
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""")
val decoded = jsonAdapter.fromJson("""{"b":6}""")!!
assertThat(decoded.a).isEqualTo(-1)
assertThat(decoded.b).isEqualTo(6)
}
@JsonClass(generateAdapter = true)
class ConstructorDefaultValues(var a: Int = -1, var b: Int = -2)
@Test fun requiredValueAbsent() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(RequiredValueAbsent::class.java)
try {
jsonAdapter.fromJson("""{"a":4}""")
fail()
} catch(expected: JsonDataException) {
assertThat(expected).hasMessage("Required property 'b' missing at \$")
}
}
@JsonClass(generateAdapter = true)
class RequiredValueAbsent(var a: Int = 3, var b: Int)
@Test fun nonNullConstructorParameterCalledWithNullFailsWithJsonDataException() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(HasNonNullConstructorParameter::class.java)
try {
jsonAdapter.fromJson("{\"a\":null}")
fail()
} catch (expected: JsonDataException) {
assertThat(expected).hasMessage("Unexpected null at \$.a")
}
}
@Test fun nonNullConstructorParameterCalledWithNullFromAdapterFailsWithJsonDataException() {
val moshi = Moshi.Builder().add(object {
@FromJson fun fromJson(string: String): String? = null
}).build()
val jsonAdapter = moshi.adapter(HasNonNullConstructorParameter::class.java)
try {
jsonAdapter.fromJson("{\"a\":\"hello\"}")
fail()
} catch (expected: JsonDataException) {
assertThat(expected).hasMessage("Non-null value 'a' was null at \$.a")
}
}
@JsonClass(generateAdapter = true)
class HasNonNullConstructorParameter(val a: String)
@Test fun explicitNull() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(ExplicitNull::class.java)
val encoded = ExplicitNull(null, 5)
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"b":5}""")
assertThat(jsonAdapter.serializeNulls().toJson(encoded)).isEqualTo("""{"a":null,"b":5}""")
val decoded = jsonAdapter.fromJson("""{"a":null,"b":6}""")!!
assertThat(decoded.a).isEqualTo(null)
assertThat(decoded.b).isEqualTo(6)
}
@JsonClass(generateAdapter = true)
class ExplicitNull(var a: Int?, var b: Int?)
@Test fun absentNull() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(AbsentNull::class.java)
val encoded = AbsentNull(null, 5)
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"b":5}""")
assertThat(jsonAdapter.serializeNulls().toJson(encoded)).isEqualTo("""{"a":null,"b":5}""")
val decoded = jsonAdapter.fromJson("""{"b":6}""")!!
assertThat(decoded.a).isNull()
assertThat(decoded.b).isEqualTo(6)
}
@JsonClass(generateAdapter = true)
class AbsentNull(var a: Int?, var b: Int?)
@Test fun constructorParameterWithQualifier() {
val moshi = Moshi.Builder()
.add(UppercaseJsonAdapter())
.build()
val jsonAdapter = moshi.adapter(ConstructorParameterWithQualifier::class.java)
val encoded = ConstructorParameterWithQualifier("Android", "Banana")
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":"ANDROID","b":"Banana"}""")
val decoded = jsonAdapter.fromJson("""{"a":"Android","b":"Banana"}""")!!
assertThat(decoded.a).isEqualTo("android")
assertThat(decoded.b).isEqualTo("Banana")
}
@JsonClass(generateAdapter = true)
class ConstructorParameterWithQualifier(@Uppercase(inFrench = true) var a: String, var b: String)
@Test fun propertyWithQualifier() {
val moshi = Moshi.Builder()
.add(UppercaseJsonAdapter())
.build()
val jsonAdapter = moshi.adapter(PropertyWithQualifier::class.java)
val encoded = PropertyWithQualifier()
encoded.a = "Android"
encoded.b = "Banana"
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":"ANDROID","b":"Banana"}""")
val decoded = jsonAdapter.fromJson("""{"a":"Android","b":"Banana"}""")!!
assertThat(decoded.a).isEqualTo("android")
assertThat(decoded.b).isEqualTo("Banana")
}
@JsonClass(generateAdapter = true)
class PropertyWithQualifier {
@Uppercase(inFrench = true) var a: String = ""
var b: String = ""
}
@Test fun constructorParameterWithJsonName() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(ConstructorParameterWithJsonName::class.java)
val encoded = ConstructorParameterWithJsonName(3, 5)
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"key a":3,"b":5}""")
val decoded = jsonAdapter.fromJson("""{"key a":4,"b":6}""")!!
assertThat(decoded.a).isEqualTo(4)
assertThat(decoded.b).isEqualTo(6)
}
@JsonClass(generateAdapter = true)
class ConstructorParameterWithJsonName(@Json(name = "key a") var a: Int, var b: Int)
@Test fun propertyWithJsonName() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(PropertyWithJsonName::class.java)
val encoded = PropertyWithJsonName()
encoded.a = 3
encoded.b = 5
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"key a":3,"b":5}""")
val decoded = jsonAdapter.fromJson("""{"key a":4,"b":6}""")!!
assertThat(decoded.a).isEqualTo(4)
assertThat(decoded.b).isEqualTo(6)
}
@JsonClass(generateAdapter = true)
class PropertyWithJsonName {
@Json(name = "key a") var a: Int = -1
var b: Int = -1
}
@Test fun transientConstructorParameter() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(TransientConstructorParameter::class.java)
val encoded = TransientConstructorParameter(3, 5)
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"b":5}""")
val decoded = jsonAdapter.fromJson("""{"a":4,"b":6}""")!!
assertThat(decoded.a).isEqualTo(-1)
assertThat(decoded.b).isEqualTo(6)
}
@JsonClass(generateAdapter = true)
class TransientConstructorParameter(@Transient var a: Int = -1, var b: Int = -1)
@Test fun transientProperty() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(TransientProperty::class.java)
val encoded = TransientProperty()
encoded.a = 3
encoded.b = 5
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"b":5}""")
val decoded = jsonAdapter.fromJson("""{"a":4,"b":6}""")!!
assertThat(decoded.a).isEqualTo(-1)
assertThat(decoded.b).isEqualTo(6)
}
@JsonClass(generateAdapter = true)
class TransientProperty {
@Transient var a: Int = -1
var b: Int = -1
}
@Test fun nonNullPropertySetToNullFailsWithJsonDataException() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(HasNonNullProperty::class.java)
try {
jsonAdapter.fromJson("{\"a\":null}")
fail()
} catch (expected: JsonDataException) {
assertThat(expected).hasMessage("Unexpected null at \$.a")
}
}
@Test fun nonNullPropertySetToNullFromAdapterFailsWithJsonDataException() {
val moshi = Moshi.Builder().add(object {
@FromJson fun fromJson(string: String): String? = null
}).build()
val jsonAdapter = moshi.adapter(HasNonNullProperty::class.java)
try {
jsonAdapter.fromJson("{\"a\":\"hello\"}")
fail()
} catch (expected: JsonDataException) {
assertThat(expected).hasMessage("Non-null value 'a' was null at \$.a")
}
}
@JsonClass(generateAdapter = true)
class HasNonNullProperty {
var a: String = ""
}
@Test fun manyProperties32() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(ManyProperties32::class.java)
val encoded = ManyProperties32(
101, 102, 103, 104, 105,
106, 107, 108, 109, 110,
111, 112, 113, 114, 115,
116, 117, 118, 119, 120,
121, 122, 123, 124, 125,
126, 127, 128, 129, 130,
131, 132)
val json = ("""
|{
|"v01":101,"v02":102,"v03":103,"v04":104,"v05":105,
|"v06":106,"v07":107,"v08":108,"v09":109,"v10":110,
|"v11":111,"v12":112,"v13":113,"v14":114,"v15":115,
|"v16":116,"v17":117,"v18":118,"v19":119,"v20":120,
|"v21":121,"v22":122,"v23":123,"v24":124,"v25":125,
|"v26":126,"v27":127,"v28":128,"v29":129,"v30":130,
|"v31":131,"v32":132
|}
|""").trimMargin().replace("\n", "")
assertThat(jsonAdapter.toJson(encoded)).isEqualTo(json)
val decoded = jsonAdapter.fromJson(json)!!
assertThat(decoded.v01).isEqualTo(101)
assertThat(decoded.v32).isEqualTo(132)
}
@JsonClass(generateAdapter = true)
class ManyProperties32(
var v01: Int, var v02: Int, var v03: Int, var v04: Int, var v05: Int,
var v06: Int, var v07: Int, var v08: Int, var v09: Int, var v10: Int,
var v11: Int, var v12: Int, var v13: Int, var v14: Int, var v15: Int,
var v16: Int, var v17: Int, var v18: Int, var v19: Int, var v20: Int,
var v21: Int, var v22: Int, var v23: Int, var v24: Int, var v25: Int,
var v26: Int, var v27: Int, var v28: Int, var v29: Int, var v30: Int,
var v31: Int, var v32: Int)
@Test fun manyProperties33() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(ManyProperties33::class.java)
val encoded = ManyProperties33(
101, 102, 103, 104, 105,
106, 107, 108, 109, 110,
111, 112, 113, 114, 115,
116, 117, 118, 119, 120,
121, 122, 123, 124, 125,
126, 127, 128, 129, 130,
131, 132, 133)
val json = ("""
|{
|"v01":101,"v02":102,"v03":103,"v04":104,"v05":105,
|"v06":106,"v07":107,"v08":108,"v09":109,"v10":110,
|"v11":111,"v12":112,"v13":113,"v14":114,"v15":115,
|"v16":116,"v17":117,"v18":118,"v19":119,"v20":120,
|"v21":121,"v22":122,"v23":123,"v24":124,"v25":125,
|"v26":126,"v27":127,"v28":128,"v29":129,"v30":130,
|"v31":131,"v32":132,"v33":133
|}
|""").trimMargin().replace("\n", "")
assertThat(jsonAdapter.toJson(encoded)).isEqualTo(json)
val decoded = jsonAdapter.fromJson(json)!!
assertThat(decoded.v01).isEqualTo(101)
assertThat(decoded.v32).isEqualTo(132)
assertThat(decoded.v33).isEqualTo(133)
}
@JsonClass(generateAdapter = true)
class ManyProperties33(
var v01: Int, var v02: Int, var v03: Int, var v04: Int, var v05: Int,
var v06: Int, var v07: Int, var v08: Int, var v09: Int, var v10: Int,
var v11: Int, var v12: Int, var v13: Int, var v14: Int, var v15: Int,
var v16: Int, var v17: Int, var v18: Int, var v19: Int, var v20: Int,
var v21: Int, var v22: Int, var v23: Int, var v24: Int, var v25: Int,
var v26: Int, var v27: Int, var v28: Int, var v29: Int, var v30: Int,
var v31: Int, var v32: Int, var v33: Int)
@Test fun unsettablePropertyIgnored() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(UnsettableProperty::class.java)
val encoded = UnsettableProperty()
encoded.b = 5
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"b":5}""")
val decoded = jsonAdapter.fromJson("""{"a":4,"b":6}""")!!
assertThat(decoded.a).isEqualTo(-1)
assertThat(decoded.b).isEqualTo(6)
}
@JsonClass(generateAdapter = true)
class UnsettableProperty {
val a: Int = -1
var b: Int = -1
}
@Test fun getterOnlyNoBackingField() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(GetterOnly::class.java)
val encoded = GetterOnly(3, 5)
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""")
val decoded = jsonAdapter.fromJson("""{"a":4,"b":6}""")!!
assertThat(decoded.a).isEqualTo(4)
assertThat(decoded.b).isEqualTo(6)
assertThat(decoded.total).isEqualTo(10)
}
@JsonClass(generateAdapter = true)
class GetterOnly(var a: Int, var b: Int) {
val total : Int
get() = a + b
}
@Test fun getterAndSetterNoBackingField() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(GetterAndSetter::class.java)
val encoded = GetterAndSetter(3, 5)
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5,"total":8}""")
// Whether b is 6 or 7 is an implementation detail. Currently we call constructors then setters.
val decoded1 = jsonAdapter.fromJson("""{"a":4,"b":6,"total":11}""")!!
assertThat(decoded1.a).isEqualTo(4)
assertThat(decoded1.b).isEqualTo(7)
assertThat(decoded1.total).isEqualTo(11)
// Whether b is 6 or 7 is an implementation detail. Currently we call constructors then setters.
val decoded2 = jsonAdapter.fromJson("""{"a":4,"total":11,"b":6}""")!!
assertThat(decoded2.a).isEqualTo(4)
assertThat(decoded2.b).isEqualTo(7)
assertThat(decoded2.total).isEqualTo(11)
}
@JsonClass(generateAdapter = true)
class GetterAndSetter(var a: Int, var b: Int) {
var total : Int
get() = a + b
set(value) {
b = value - a
}
}
@Test fun supertypeConstructorParameters() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(SubtypeConstructorParameters::class.java)
val encoded = SubtypeConstructorParameters(3, 5)
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""")
val decoded = jsonAdapter.fromJson("""{"a":4,"b":6}""")!!
assertThat(decoded.a).isEqualTo(4)
assertThat(decoded.b).isEqualTo(6)
}
open class SupertypeConstructorParameters(var a: Int)
@JsonClass(generateAdapter = true)
class SubtypeConstructorParameters(a: Int, var b: Int) : SupertypeConstructorParameters(a)
@Test fun supertypeProperties() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(SubtypeProperties::class.java)
val encoded = SubtypeProperties()
encoded.a = 3
encoded.b = 5
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"b":5,"a":3}""")
val decoded = jsonAdapter.fromJson("""{"a":4,"b":6}""")!!
assertThat(decoded.a).isEqualTo(4)
assertThat(decoded.b).isEqualTo(6)
}
open class SupertypeProperties {
var a: Int = -1
}
@JsonClass(generateAdapter = true)
class SubtypeProperties : SupertypeProperties() {
var b: Int = -1
}
/** Generated adapters don't track enough state to detect duplicated values. */
@Ignore @Test fun duplicatedValue() {
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(DuplicateValue::class.java)
try {
jsonAdapter.fromJson("""{"a":4,"a":4}""")
fail()
} catch(expected: JsonDataException) {
assertThat(expected).hasMessage("Multiple values for a at $.a")
}
}
@JsonClass(generateAdapter = true)
class DuplicateValue(var a: Int = -1, var b: Int = -2)
@JsonQualifier
annotation class Uppercase(val inFrench: Boolean, val onSundays: Boolean = false)
class UppercaseJsonAdapter {
@ToJson fun toJson(@Uppercase(inFrench = true) s: String) : String {
return s.toUpperCase(Locale.US)
}
@FromJson @Uppercase(inFrench = true) fun fromJson(s: String) : String {
return s.toLowerCase(Locale.US)
}
}
}
// Has to be outside to avoid Types seeing an owning class
@JsonClass(generateAdapter = true)
data class NullableTypeParams<T>(
val nullableList: List<String?>,
val nullableSet: Set<String?>,
val nullableMap: Map<String, String?>,
val nullableT: T?,
val nonNullT: T
)
typealias TypeAliasName = String
/**
* This is here mostly just to ensure it still compiles. Covers variance, @Json, default values,
* nullability, primitive arrays, and some wacky generics.
*/
@JsonClass(generateAdapter = true)
data class SmokeTestType(
@Json(name = "first_name") val firstName: String,
@Json(name = "last_name") val lastName: String,
val age: Int,
val nationalities: List<String> = emptyList(),
val weight: Float,
val tattoos: Boolean = false,
val race: String?,
val hasChildren: Boolean = false,
val favoriteFood: String? = null,
val favoriteDrink: String? = "Water",
val wildcardOut: List<out String> = emptyList(),
val wildcardIn: Array<in String>,
val any: List<*>,
val anyTwo: List<Any>,
val anyOut: List<out Any>,
val favoriteThreeNumbers: IntArray,
val favoriteArrayValues: Array<String>,
val favoriteNullableArrayValues: Array<String?>,
val nullableSetListMapArrayNullableIntWithDefault: Set<List<Map<String, Array<IntArray?>>>>? = null,
val aliasedName: TypeAliasName = "Woah"
)