mirror of
https://github.com/fankes/moshi.git
synced 2025-10-19 16:09:21 +08:00
Merge pull request #473 from square/jwilson.0403.qualifiers_names_transient
Handle qualifiers, names, and transient in generated adapters
This commit is contained in:
@@ -27,6 +27,7 @@ import me.eugeniomarletti.kotlin.metadata.KotlinClassMetadata
|
|||||||
import me.eugeniomarletti.kotlin.metadata.KotlinMetadataUtils
|
import me.eugeniomarletti.kotlin.metadata.KotlinMetadataUtils
|
||||||
import me.eugeniomarletti.kotlin.metadata.classKind
|
import me.eugeniomarletti.kotlin.metadata.classKind
|
||||||
import me.eugeniomarletti.kotlin.metadata.declaresDefaultValue
|
import me.eugeniomarletti.kotlin.metadata.declaresDefaultValue
|
||||||
|
import me.eugeniomarletti.kotlin.metadata.getPropertyOrNull
|
||||||
import me.eugeniomarletti.kotlin.metadata.isDataClass
|
import me.eugeniomarletti.kotlin.metadata.isDataClass
|
||||||
import me.eugeniomarletti.kotlin.metadata.isPrimary
|
import me.eugeniomarletti.kotlin.metadata.isPrimary
|
||||||
import me.eugeniomarletti.kotlin.metadata.jvm.getJvmConstructorSignature
|
import me.eugeniomarletti.kotlin.metadata.jvm.getJvmConstructorSignature
|
||||||
@@ -34,6 +35,7 @@ import me.eugeniomarletti.kotlin.metadata.kotlinMetadata
|
|||||||
import me.eugeniomarletti.kotlin.metadata.visibility
|
import me.eugeniomarletti.kotlin.metadata.visibility
|
||||||
import me.eugeniomarletti.kotlin.processing.KotlinAbstractProcessor
|
import me.eugeniomarletti.kotlin.processing.KotlinAbstractProcessor
|
||||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||||
|
import org.jetbrains.kotlin.serialization.ProtoBuf.Property
|
||||||
import org.jetbrains.kotlin.serialization.ProtoBuf.ValueParameter
|
import org.jetbrains.kotlin.serialization.ProtoBuf.ValueParameter
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.annotation.processing.ProcessingEnvironment
|
import javax.annotation.processing.ProcessingEnvironment
|
||||||
@@ -44,6 +46,7 @@ import javax.lang.model.element.AnnotationMirror
|
|||||||
import javax.lang.model.element.Element
|
import javax.lang.model.element.Element
|
||||||
import javax.lang.model.element.ElementKind
|
import javax.lang.model.element.ElementKind
|
||||||
import javax.lang.model.element.ExecutableElement
|
import javax.lang.model.element.ExecutableElement
|
||||||
|
import javax.lang.model.element.Modifier
|
||||||
import javax.lang.model.element.TypeElement
|
import javax.lang.model.element.TypeElement
|
||||||
import javax.lang.model.element.VariableElement
|
import javax.lang.model.element.VariableElement
|
||||||
import javax.tools.Diagnostic.Kind.ERROR
|
import javax.tools.Diagnostic.Kind.ERROR
|
||||||
@@ -159,6 +162,14 @@ class JsonClassCodeGenProcessor : KotlinAbstractProcessor(), KotlinMetadataUtils
|
|||||||
nameResolver.getString(it.name)
|
nameResolver.getString(it.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The compiler might emit methods just so it has a place to put annotations. Find these.
|
||||||
|
val annotatedElements = mutableMapOf<Property, ExecutableElement>()
|
||||||
|
for (enclosedElement in element.enclosedElements) {
|
||||||
|
if (enclosedElement !is ExecutableElement) continue
|
||||||
|
val property = classData.getPropertyOrNull(enclosedElement) ?: continue
|
||||||
|
annotatedElements[property] = enclosedElement
|
||||||
|
}
|
||||||
|
|
||||||
val propertyGenerators = mutableListOf<PropertyGenerator>()
|
val propertyGenerators = mutableListOf<PropertyGenerator>()
|
||||||
for (enclosedElement in element.enclosedElements) {
|
for (enclosedElement in element.enclosedElements) {
|
||||||
if (enclosedElement !is VariableElement) continue
|
if (enclosedElement !is VariableElement) continue
|
||||||
@@ -174,6 +185,8 @@ class JsonClassCodeGenProcessor : KotlinAbstractProcessor(), KotlinMetadataUtils
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val annotatedElement = annotatedElements[property]
|
||||||
|
|
||||||
if (property.visibility != ProtoBuf.Visibility.INTERNAL
|
if (property.visibility != ProtoBuf.Visibility.INTERNAL
|
||||||
&& property.visibility != ProtoBuf.Visibility.PROTECTED
|
&& property.visibility != ProtoBuf.Visibility.PROTECTED
|
||||||
&& property.visibility != ProtoBuf.Visibility.PUBLIC) {
|
&& property.visibility != ProtoBuf.Visibility.PUBLIC) {
|
||||||
@@ -181,15 +194,24 @@ class JsonClassCodeGenProcessor : KotlinAbstractProcessor(), KotlinMetadataUtils
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val hasDefault = parameter?.declaresDefaultValue ?: true
|
||||||
|
|
||||||
|
if (enclosedElement.modifiers.contains(Modifier.TRANSIENT)) {
|
||||||
|
if (!hasDefault) {
|
||||||
|
throw IllegalArgumentException("No default value for transient property $name")
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
propertyGenerators += PropertyGenerator(
|
propertyGenerators += PropertyGenerator(
|
||||||
name,
|
name,
|
||||||
serializedName(name, enclosedElement, parameterElement),
|
jsonName(name, enclosedElement, annotatedElement, parameterElement),
|
||||||
parameter != null,
|
parameter != null,
|
||||||
parameter?.declaresDefaultValue ?: true,
|
hasDefault,
|
||||||
property.returnType.nullable,
|
property.returnType.nullable,
|
||||||
property.returnType.asTypeName(nameResolver, classProto::getTypeParameter),
|
property.returnType.asTypeName(nameResolver, classProto::getTypeParameter),
|
||||||
property.returnType.asTypeName(nameResolver, classProto::getTypeParameter, true),
|
property.returnType.asTypeName(nameResolver, classProto::getTypeParameter, true),
|
||||||
jsonQualifiers(enclosedElement, parameterElement))
|
jsonQualifiers(enclosedElement, annotatedElement, parameterElement))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort properties so that those with constructor parameters come first.
|
// Sort properties so that those with constructor parameters come first.
|
||||||
@@ -234,38 +256,39 @@ class JsonClassCodeGenProcessor : KotlinAbstractProcessor(), KotlinMetadataUtils
|
|||||||
/** Returns the JsonQualifiers on the field and parameter of a property. */
|
/** Returns the JsonQualifiers on the field and parameter of a property. */
|
||||||
private fun jsonQualifiers(
|
private fun jsonQualifiers(
|
||||||
field: VariableElement,
|
field: VariableElement,
|
||||||
|
method: ExecutableElement?,
|
||||||
parameter: VariableElement?
|
parameter: VariableElement?
|
||||||
): Set<AnnotationMirror> {
|
): Set<AnnotationMirror> {
|
||||||
val fieldJsonQualifiers = AnnotationMirrors.getAnnotatedAnnotations(
|
val fieldQualifiers = field.qualifiers
|
||||||
field, JsonQualifier::class.java)
|
val methodQualifiers = method.qualifiers
|
||||||
|
val parameterQualifiers = parameter.qualifiers
|
||||||
val parameterJsonQualifiers: Set<AnnotationMirror> = if (parameter != null) {
|
|
||||||
AnnotationMirrors.getAnnotatedAnnotations(parameter, JsonQualifier::class.java)
|
|
||||||
} else {
|
|
||||||
setOf()
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(jwilson): union the qualifiers somehow?
|
// TODO(jwilson): union the qualifiers somehow?
|
||||||
if (fieldJsonQualifiers.isNotEmpty()) {
|
return when {
|
||||||
return fieldJsonQualifiers
|
fieldQualifiers.isNotEmpty() -> fieldQualifiers
|
||||||
} else {
|
methodQualifiers.isNotEmpty() -> methodQualifiers
|
||||||
return parameterJsonQualifiers
|
parameterQualifiers.isNotEmpty() -> parameterQualifiers
|
||||||
|
else -> setOf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the @Json name of a property, or `propertyName` if none is provided. */
|
/** Returns the @Json name of a property, or `propertyName` if none is provided. */
|
||||||
private fun serializedName(
|
private fun jsonName(
|
||||||
propertyName: String,
|
propertyName: String,
|
||||||
field: VariableElement,
|
field: VariableElement,
|
||||||
|
method: ExecutableElement?,
|
||||||
parameter: VariableElement?
|
parameter: VariableElement?
|
||||||
): String {
|
): String {
|
||||||
val fieldAnnotation = field.getAnnotation(Json::class.java)
|
val fieldJsonName = field.jsonName
|
||||||
if (fieldAnnotation != null) return fieldAnnotation.name
|
val methodJsonName = method.jsonName
|
||||||
|
val parameterJsonName = parameter.jsonName
|
||||||
|
|
||||||
val parameterAnnotation = parameter?.getAnnotation(Json::class.java)
|
return when {
|
||||||
if (parameterAnnotation != null) return parameterAnnotation.name
|
fieldJsonName != null -> fieldJsonName
|
||||||
|
methodJsonName != null -> methodJsonName
|
||||||
return propertyName
|
parameterJsonName != null -> parameterJsonName
|
||||||
|
else -> propertyName
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun errorMustBeKotlinClass(element: Element) {
|
private fun errorMustBeKotlinClass(element: Element) {
|
||||||
@@ -287,5 +310,16 @@ class JsonClassCodeGenProcessor : KotlinAbstractProcessor(), KotlinMetadataUtils
|
|||||||
val file = filer.createSourceFile(adapterName).toUri().let(::File)
|
val file = filer.createSourceFile(adapterName).toUri().let(::File)
|
||||||
return file.parentFile.also { file.delete() }
|
return file.parentFile.also { file.delete() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val Element?.qualifiers: Set<AnnotationMirror>
|
||||||
|
get() {
|
||||||
|
if (this == null) return setOf()
|
||||||
|
return AnnotationMirrors.getAnnotatedAnnotations(this, JsonQualifier::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val Element?.jsonName: String?
|
||||||
|
get() {
|
||||||
|
if (this == null) return null
|
||||||
|
return getAnnotation(Json::class.java)?.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -52,7 +52,7 @@ internal class PropertyGenerator(
|
|||||||
|
|
||||||
fun reserveDelegateNames(nameAllocator: NameAllocator) {
|
fun reserveDelegateNames(nameAllocator: NameAllocator) {
|
||||||
val qualifierNames = jsonQualifiers.joinToString("") {
|
val qualifierNames = jsonQualifiers.joinToString("") {
|
||||||
"at${it.annotationType.asElement().simpleName.toString().capitalize()}"
|
"At${it.annotationType.asElement().simpleName.toString().capitalize()}"
|
||||||
}
|
}
|
||||||
nameAllocator.newName("${unaliasedName.toVariableName()}${qualifierNames}Adapter",
|
nameAllocator.newName("${unaliasedName.toVariableName()}${qualifierNames}Adapter",
|
||||||
delegateKey())
|
delegateKey())
|
||||||
|
@@ -16,9 +16,10 @@
|
|||||||
package com.squareup.moshi
|
package com.squareup.moshi
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.assertj.core.api.Assertions.fail
|
|
||||||
import org.intellij.lang.annotations.Language
|
import org.intellij.lang.annotations.Language
|
||||||
|
import org.junit.Assert.fail
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
class GeneratedAdaptersTest {
|
class GeneratedAdaptersTest {
|
||||||
|
|
||||||
@@ -353,6 +354,190 @@ class GeneratedAdaptersTest {
|
|||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
class ConstructorDefaultValues(var a: Int = -1, var b: Int = -2)
|
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("Required property 'a' missing at \$")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 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 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
|
||||||
|
}
|
||||||
|
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@JsonQualifier
|
||||||
|
annotation class Uppercase
|
||||||
|
|
||||||
|
class UppercaseJsonAdapter {
|
||||||
|
@ToJson fun toJson(@Uppercase s: String) : String {
|
||||||
|
return s.toUpperCase(Locale.US)
|
||||||
|
}
|
||||||
|
@FromJson @Uppercase fun fromJson(s: String) : String {
|
||||||
|
return s.toLowerCase(Locale.US)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has to be outside to avoid Types seeing an owning class
|
// Has to be outside to avoid Types seeing an owning class
|
||||||
|
@@ -25,33 +25,19 @@ import java.util.SimpleTimeZone
|
|||||||
import kotlin.annotation.AnnotationRetention.RUNTIME
|
import kotlin.annotation.AnnotationRetention.RUNTIME
|
||||||
|
|
||||||
class KotlinCodeGenTest {
|
class KotlinCodeGenTest {
|
||||||
@Ignore @Test fun requiredValueAbsent() {
|
@Ignore @Test fun duplicatedValue() {
|
||||||
val moshi = Moshi.Builder().build()
|
val moshi = Moshi.Builder().build()
|
||||||
val jsonAdapter = moshi.adapter(RequiredValueAbsent::class.java)
|
val jsonAdapter = moshi.adapter(DuplicateValue::class.java)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
jsonAdapter.fromJson("""{"a":4}""")
|
jsonAdapter.fromJson("""{"a":4,"a":4}""")
|
||||||
fail()
|
fail()
|
||||||
} catch(expected: JsonDataException) {
|
} catch(expected: JsonDataException) {
|
||||||
assertThat(expected).hasMessage("Required value b missing at $")
|
assertThat(expected).hasMessage("Multiple values for a at $.a")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RequiredValueAbsent(var a: Int = 3, var b: Int)
|
class DuplicateValue(var a: Int = -1, var b: Int = -2)
|
||||||
|
|
||||||
@Ignore @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("Non-null value a was null at \$")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class HasNonNullConstructorParameter(val a: String)
|
|
||||||
|
|
||||||
@Ignore @Test fun nonNullPropertySetToNullFailsWithJsonDataException() {
|
@Ignore @Test fun nonNullPropertySetToNullFailsWithJsonDataException() {
|
||||||
val moshi = Moshi.Builder().build()
|
val moshi = Moshi.Builder().build()
|
||||||
@@ -69,50 +55,6 @@ class KotlinCodeGenTest {
|
|||||||
var a: String = ""
|
var a: String = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DuplicateValue(var a: Int = -1, var b: Int = -2)
|
|
||||||
|
|
||||||
@Ignore @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)
|
|
||||||
}
|
|
||||||
|
|
||||||
class ExplicitNull(var a: Int?, var b: Int?)
|
|
||||||
|
|
||||||
@Ignore @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)
|
|
||||||
}
|
|
||||||
|
|
||||||
class AbsentNull(var a: Int?, var b: Int?)
|
|
||||||
|
|
||||||
@Ignore @Test fun repeatedValue() {
|
@Ignore @Test fun repeatedValue() {
|
||||||
val moshi = Moshi.Builder().build()
|
val moshi = Moshi.Builder().build()
|
||||||
val jsonAdapter = moshi.adapter(RepeatedValue::class.java)
|
val jsonAdapter = moshi.adapter(RepeatedValue::class.java)
|
||||||
@@ -127,90 +69,6 @@ class KotlinCodeGenTest {
|
|||||||
|
|
||||||
class RepeatedValue(var a: Int, var b: Int?)
|
class RepeatedValue(var a: Int, var b: Int?)
|
||||||
|
|
||||||
@Ignore @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")
|
|
||||||
}
|
|
||||||
|
|
||||||
class ConstructorParameterWithQualifier(@Uppercase var a: String, var b: String)
|
|
||||||
|
|
||||||
@Ignore @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")
|
|
||||||
}
|
|
||||||
|
|
||||||
class PropertyWithQualifier {
|
|
||||||
@Uppercase var a: String = ""
|
|
||||||
var b: String = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore @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)
|
|
||||||
}
|
|
||||||
|
|
||||||
class ConstructorParameterWithJsonName(@Json(name = "key a") var a: Int, var b: Int)
|
|
||||||
|
|
||||||
@Ignore @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)
|
|
||||||
}
|
|
||||||
|
|
||||||
class PropertyWithJsonName {
|
|
||||||
@Json(name = "key a") var a: Int = -1
|
|
||||||
var b: Int = -1
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore @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)
|
|
||||||
}
|
|
||||||
|
|
||||||
class TransientConstructorParameter(@Transient var a: Int = -1, var b: Int = -1)
|
|
||||||
|
|
||||||
@Ignore @Test fun requiredTransientConstructorParameterFails() {
|
@Ignore @Test fun requiredTransientConstructorParameterFails() {
|
||||||
val moshi = Moshi.Builder().build()
|
val moshi = Moshi.Builder().build()
|
||||||
try {
|
try {
|
||||||
@@ -225,25 +83,6 @@ class KotlinCodeGenTest {
|
|||||||
|
|
||||||
class RequiredTransientConstructorParameter(@Transient var a: Int)
|
class RequiredTransientConstructorParameter(@Transient var a: Int)
|
||||||
|
|
||||||
@Ignore @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)
|
|
||||||
}
|
|
||||||
|
|
||||||
class TransientProperty {
|
|
||||||
@Transient var a: Int = -1
|
|
||||||
var b: Int = -1
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore @Test fun supertypeConstructorParameters() {
|
@Ignore @Test fun supertypeConstructorParameters() {
|
||||||
val moshi = Moshi.Builder().build()
|
val moshi = Moshi.Builder().build()
|
||||||
val jsonAdapter = moshi.adapter(SubtypeConstructorParameters::class.java)
|
val jsonAdapter = moshi.adapter(SubtypeConstructorParameters::class.java)
|
||||||
|
Reference in New Issue
Block a user