mirror of
https://github.com/fankes/moshi.git
synced 2025-10-20 00:19:21 +08:00
Support more kinds of properties in KotlinJsonAdapter
This makes it possible to have synthetic properties that have no state. Also test properties that are synthetic and have no backing field. Closes: https://github.com/square/moshi/issues/299
This commit is contained in:
@@ -115,12 +115,6 @@ internal class KotlinJsonAdapter<T>(
|
|||||||
val adapter: JsonAdapter<P>,
|
val adapter: JsonAdapter<P>,
|
||||||
val property: KProperty1<K, P>,
|
val property: KProperty1<K, P>,
|
||||||
val parameter: KParameter?) {
|
val parameter: KParameter?) {
|
||||||
init {
|
|
||||||
if (property !is KMutableProperty1 && parameter == null) {
|
|
||||||
throw IllegalArgumentException("No constructor or var property for ${property}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun get(value: K) = property.get(value)
|
fun get(value: K) = property.get(value)
|
||||||
|
|
||||||
fun set(result: K, value: P) {
|
fun set(result: K, value: P) {
|
||||||
@@ -171,11 +165,13 @@ object KotlinJsonAdapterFactory : JsonAdapter.Factory {
|
|||||||
for (property in rawType.kotlin.memberProperties) {
|
for (property in rawType.kotlin.memberProperties) {
|
||||||
if (Modifier.isTransient(property.javaField?.modifiers ?: 0)) continue
|
if (Modifier.isTransient(property.javaField?.modifiers ?: 0)) continue
|
||||||
|
|
||||||
|
val parameter = parametersByName[property.name]
|
||||||
|
if (property !is KMutableProperty1 && parameter == null) continue
|
||||||
|
|
||||||
property.isAccessible = true
|
property.isAccessible = true
|
||||||
var allAnnotations = property.annotations
|
var allAnnotations = property.annotations
|
||||||
var jsonAnnotation = property.findAnnotation<Json>()
|
var jsonAnnotation = property.findAnnotation<Json>()
|
||||||
|
|
||||||
val parameter = parametersByName[property.name]
|
|
||||||
if (parameter != null) {
|
if (parameter != null) {
|
||||||
allAnnotations += parameter.annotations
|
allAnnotations += parameter.annotations
|
||||||
if (jsonAnnotation == null) {
|
if (jsonAnnotation == null) {
|
||||||
|
@@ -445,15 +445,17 @@ class KotlinJsonAdapterTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun unsettableProperty() {
|
@Test fun unsettablePropertyIgnored() {
|
||||||
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build()
|
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build()
|
||||||
try {
|
val jsonAdapter = moshi.adapter(UnsettableProperty::class.java)
|
||||||
moshi.adapter(UnsettableProperty::class.java)
|
|
||||||
fail()
|
val encoded = UnsettableProperty()
|
||||||
} catch(expected: IllegalArgumentException) {
|
encoded.b = 5
|
||||||
assertThat(expected).hasMessage("No constructor or var property for " +
|
assertThat(jsonAdapter.toJson(encoded)).isEqualTo("{\"b\":5}")
|
||||||
"val ${UnsettableProperty::class.qualifiedName}.a: kotlin.Int")
|
|
||||||
}
|
val decoded = jsonAdapter.fromJson("{\"a\":4,\"b\":6}")!!
|
||||||
|
assertThat(decoded.a).isEqualTo(-1)
|
||||||
|
assertThat(decoded.b).isEqualTo(6)
|
||||||
}
|
}
|
||||||
|
|
||||||
class UnsettableProperty {
|
class UnsettableProperty {
|
||||||
@@ -461,6 +463,52 @@ class KotlinJsonAdapterTest {
|
|||||||
var b: Int = -1
|
var b: Int = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test fun getterOnlyNoBackingField() {
|
||||||
|
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).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)
|
||||||
|
}
|
||||||
|
|
||||||
|
class GetterOnly(var a: Int, var b: Int) {
|
||||||
|
val total : Int
|
||||||
|
get() = a + b
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun getterAndSetterNoBackingField() {
|
||||||
|
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).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)
|
||||||
|
}
|
||||||
|
|
||||||
|
class GetterAndSetter(var a: Int, var b: Int) {
|
||||||
|
var total : Int
|
||||||
|
get() = a + b
|
||||||
|
set(value) {
|
||||||
|
b = value - a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test fun nonPropertyConstructorParameter() {
|
@Test fun nonPropertyConstructorParameter() {
|
||||||
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build()
|
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build()
|
||||||
try {
|
try {
|
||||||
|
Reference in New Issue
Block a user