Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one manually convert Apollo Android-generated objects into JSON strings and back?

I use the Apollo Android library to make queries to a GraphQL endpoint. Everything works OK until I try to convert the results back to JSON strings (to store them in a Room database). I naively tried to use Moshi, however this fails with the following error:

Cannot get available extra products: No JsonAdapter for interface com.example.MyQuery$MyFragmentInterface

where MyFragmentInterface in an interface generated by Apollo to handle query fragments.

So, I tried to find whether the Apollo library has/generates any conversion methods, i.e. sth like toJson()/fromJson(), for the generated models, however I couldn't find anything usable.

Am I missing something obvious?

like image 280
Giorgos Kylafas Avatar asked Dec 19 '19 16:12

Giorgos Kylafas


2 Answers

Here is an example how you can deserialize string as generated object. Inlined comments for further details.

// Sample string response
val jsonResponse = """
{
  "data": {
  {
    "id": "isbn-889-333",
    "title": "Awesome title",
    "rating": 5
  }
}
""".trimIndent()

// Create query that is expect to return above response
val query = QueryBookDetails("book_id")

// convert string to input stream
val inputStream = ByteArrayInputStream(jsonResponse.toByteArray())

// Read bytes into okio buffer
val buffer = Buffer().readFrom(inputStream)

// Use the query to parse the buffer. 
val response = query.parse(buffer)

// response.data might be the one needed by you

Bear in mind that the response must honour the schema.

like image 121
Mahendran Avatar answered Sep 19 '22 20:09

Mahendran


Since Apollo 1.3.x there is an Operation.Data.toJson() extension function (Kotlin) and a corresponding serialize static method in Java. Check https://www.apollographql.com/docs/android/advanced/no-runtime/#converting-querydata-back-to-json

For the opposite, Json string to Query.Data, I use something like the following:

fun String?.toMyData(): MyQuery.Data? {
    this ?: return null
    val query = MyQuery()
    val response: Response<MyQuery.Data> =
        OperationResponseParser(query,
                                query.responseFieldMapper(),
                                ScalarTypeAdapters.DEFAULT)
            .parse(Buffer().writeUtf8(this))
    return response.data
}
like image 29
Giorgos Kylafas Avatar answered Sep 22 '22 20:09

Giorgos Kylafas