kamikat / moshi-jsonapi

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

Trouble with HasOne relationship #86

Closed taynanbonaldo closed 5 years ago

taynanbonaldo commented 5 years ago

Hi,

I'm using moshi-jsonapi and moshi-jsonapi-retrofit-converter 3.5.0 with moshi and moshi-kotlin 1.8.0 to parse response of my API.

I have 3 classes:

Voucher

import com.squareup.moshi.Json
import moe.banana.jsonapi2.JsonApi
import moe.banana.jsonapi2.Resource
import moe.banana.jsonapi2.HasMany
import moe.banana.jsonapi2.HasOne

@JsonApi(type = "voucher")
class Voucher : Resource() {

    @Expose
    var name: String? = null

    @Expose
    var status: String? = null

    @Expose
    var url: String? = null

    var coverImage: HasOne<CoverImage>? = null

    var stores: HasMany<Store>? = null

    fun getCover() : CoverImage? {
        return coverImage?.get(document)
    }

    fun getStores() : List<Store>? {
        return stores?.get(document)
    }

}

CoverImage

import com.squareup.moshi.Json
import moe.banana.jsonapi2.JsonApi
import moe.banana.jsonapi2.Resource

@JsonApi(type = "cover_image")
class CoverImage : Resource() {

    @Json(name = "updated_at")
    var updatedAt: String? = null

    @Expose
    var url: String? = null

    @Json(name = "thumb_url")
    var thumbUrl: String? = null
}

Store

import com.google.gson.annotations.Expose
import moe.banana.jsonapi2.JsonApi
import moe.banana.jsonapi2.Resource

@JsonApi(type = "store")
class Store : Resource() {

    @Expose
    var name: String? = null

    @Expose
    var address: String? = null

    @Expose
    var latitude: Double? = null

    @Expose
    var longitude: Double? = null

}

And my API:

@GET("/api/vouchers.json")
    fun fetchVouchers (
            @Query("page") page: Int,
            @Query("page_size") page_size: Int? = DEFAULT_PAGE_SIZE
    ) : Flowable<ArrayDocument<Voucher>>

The response is parsed succeed, as well has "included" array parsed with CoverImage and Stores.

But when I get a Voucher Document from ArrayDocument response and try to retrieve its CoverImage, its null. However, when I read Stores, the array was populated with itens related to Voucher as expected.

Here is my Json response:

{
    "data": [{
        "id": "2",
        "type": "voucher",
        "attributes": {
            "id": 2,
            "name": "Voucher Name",
            "status": "published",
            "url": "http://url"
        },
        "relationships": {
            "cover_image": {
                "data": {
                    "id": "21",
                    "type": "cover_image"
                }
            },
            "stores": {
                "data": [ {
                    "id": "28",
                    "type": "store"
                }, {
                    "id": "13",
                    "type": "store"
                }]
            }
        }
    }],
    "included": [{
        "id": "21",
        "type": "cover_image",
        "attributes": {
            "id": 21,
            "updated_at": "2018-11-19 18:07:30 -0200",
            "url": "https://coverurl",
            "thumb_url": "https://thumburl"
        }
    }, {
        "id": "28",
        "type": "store",
        "attributes": {
            "name": "Store Name 1",
            "address": "Store Address",
            "latitude": -12.345,
            "longitude": -12.345
        }
    }, {
        "id": "13",
        "type": "store",
        "attributes": {
            "name": "Store Name 2",
            "address": "Store Address",
            "latitude": -12.345,
            "longitude": -12.345
        }
    }]
}

I'm doing anything wrong? Why HasOne relation wasn't resolved?

taynanbonaldo commented 5 years ago

I tried to use Java instead of Kotlin in my POJOs (and removing moshi-kotlin dependency).

I tried to intercept API response using OkHttp and convert "JsonObject" relationship to "JsonArray" (because array of stores relationship works!).

I tried to remove "stores" from relationship to see if with "cover_image" isolated would work.

I tried to rename entities, delete and re-create them, rename json keys.

But none of the attempts was successfully.

The more stranger here is that all "cover_image" and "store" objects are on Moshi Document "included" array. As well I can access the cover_image object using document.find< CoverImage >(ResourceIdentifier).

Why it not fill in my HasOne< CoverImage > attribute?

Any suggestion?

kamikat commented 5 years ago

Missing @Json(name = "cover_image") on Voucher.coverImage?

taynanbonaldo commented 5 years ago

You are totally right! I feel ashamed for not having tried this simple alternative! I had not thought of that, because I thought that by using the "HasOne" type it was not necessary to add the annotation ... it was extremely wrong! Would it be the case to add this information in Read Me? Or is this too obvious to be added? Hehehe

Anyway, thank you very much for the attention!