0

I have an object that comes down from the API with another json object (with no named attributes) as one of its attributes:

"stickerData": {}

I would like this to be parsed into this object:

@JsonClass(generateAdapter = true)
class StickerDto(
        @Json (name = "totalAnimatedStickers") val total: Int,
        @Json(name = "pages") val pages: Int,
        @Json(name = "data") val stickers: List<Sticker>

)



@JsonClass(generateAdapter = true)
class Sticker(
        @Json(name = "name") val name: String,
        @Json(name = "id") val id: String,
        @Json(name = "stickerData") val stickerData: String,

)

The architecture of this app uses a single Retrofit instance for every API call:

private fun createNewUserApiClient(authRefreshClient: AuthRefreshClient,
                                       preferencesInteractor: PreferencesInteractor): UserApiClient {
        val moshi = Moshi.Builder()
                .add(SkipBadElementsListAdapter.Factory)
             

        return Retrofit.Builder()
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(MoshiConverterFactory.create(moshi))
                .baseUrl(Interactors.apiEndpoint)
                .build()
                .create(UserApiClient::class.java)
    }

Which, uses this adapter that you can see getting attached above:

internal class SkipBadElementsListAdapter(private val elementAdapter: JsonAdapter<Any?>) : JsonAdapter<List<Any?>>() {

    object Factory : JsonAdapter.Factory {
     
    override fun fromJson(reader: JsonReader): List<Any?>? {
        val result = mutableListOf<Any?>()
        reader.beginArray()
        while (reader.hasNext()) {
            try {
                val peeked = reader.peekJson()
                result.add(elementAdapter.fromJson(peeked))
            } catch (e: JsonDataException) {
                Timber.w(e, "Item skipped while parsing:")
            }
            reader.skipValue()
        }
        reader.endArray()
        return result
    }

}

However, this adapter does not allow for the parsing of a JSON object as a string. If I try, it throws a

Gson: Expected a string but was BEGIN_OBJECT

error. Is there any way to get this adapter to parse attributes like this as raw strings, rather than looking for an object ?

andrewedgar
  • 797
  • 1
  • 12
  • 46

1 Answers1

-1

The stickerData should be Object in POJO class, like this...

@JsonClass(generateAdapter = true)
class Sticker(
        @Json(name = "name") val name: String,
        @Json(name = "id") val id: String,
        @Json(name = "stickerData") val stickerData: StickerData,

)
andika_kurniawan
  • 511
  • 4
  • 9
  • 20
  • The attributes of the object being retrieved are unknown, it's just a JSON string with varying attributes, which I why I want it to be a string. I won't be able to give the POJO any attributes. Will it still work? – andrewedgar Jul 10 '20 at 13:52
  • yes, if there are string attributes inside stickerData. you can put in StickerData class – andika_kurniawan Jul 10 '20 at 13:59
  • Yes, but what I'm saying is the attributes are unknown and will vary by sticker. There aren't a set list of attributes I will be able to put in that class, which is why I want the raw string. – andrewedgar Jul 10 '20 at 14:14
  • @andrewedgar maybe, you need like this https://stackoverflow.com/questions/24279245/how-to-handle-dynamic-json-in-retrofit?noredirect=1&lq=1 – andika_kurniawan Jul 10 '20 at 14:44