kamikat / moshi-jsonapi

JSON API v1.0 Specification in Moshi.
MIT License
156 stars 34 forks source link

Kotlin classes with Json annotations #69

Closed dumazy closed 7 years ago

dumazy commented 7 years ago

The adapters don't work when using Kotlin classes with Json(name = "..") annotations. This is because annotations in Java are not the same as annotations in Kotlin and the adapters find no Json annotation.

The moshi readme states this:

Kotlin classes work with Moshi out of the box, with the exception of annotations. If you need to annotate your Kotlin classes with an @Json annotation or otherwise, you will need to use the moshi-kotlin artifact, and set up Moshi to use its converter factory:

val moshi = Moshi.Builder() .add(KotlinJsonAdapterFactory()) .build()

But this causes the DocumentAdapter to choose KotlinJsonAdapter as dataJsonAdapter instead of a ResourceAdapter, so the serialization to a json output with attributes, relationships, etc doesn't work.

kamikat commented 7 years ago

How about changing the order of adapter factories?

dumazy commented 7 years ago

If I put the KotlinJsonAdapterFactory after the ResourceAdapterFactory, the Json annotations are ignored. I debugged the flow and saw that KotlinJsonAdapter wasn't called. If I put the KotlinJsonAdapterFactory first, the ResourceAdapters are not called.

kamikat commented 7 years ago

Umm... Can you try the master-SNAPSHOT version to see if Builder.setJsonNameMapping (commit 90dffb97c781ce3cf3a23612bfc7416737c5c2a6) works for your case?

By implementing JsonNameMapping in Kotlin, you can use functions provided by kotlin.reflect package to provide name information about the field/property (which can only be done with Kotlin).

dumazy commented 7 years ago

I've switched my models to Java classes already. I can test it with kotlin classes when I have time. I'll let you know if it works

bricestacey commented 7 years ago

I ran into this same problem. I was able to solve it with the following

    class MoshiJsonNameMapping : JsonNameMapping {
        override fun getJsonName(field: Field): String {
            val foo = field.kotlinProperty?.findAnnotation<Json>()
            return foo?.name ?: field.name
        }
    }
Kaned1as commented 6 years ago

Another solution: Just annotate them with @field:Json instead of @Json

premnirmal commented 6 years ago

I'm experiencing the same issue. Using a json mapping didn't fix the issue for me. Any ideas? Thanks in advance.