Как десериализовать необработанные JSON объекты с помощью Moshi / Retrofit - PullRequest
3 голосов
/ 10 июля 2020

У меня есть класс стикеров и его оболочка:

@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: JsonObject,
        var isSelected:Boolean = false
)

Атрибут стикерData поступает из api с объектом Dynami c json с неизвестными атрибутами

"stickerData": {}

Как десериализовать подобный объект с помощью Moshi?

Мой текущий клиент модернизации:

 private fun createNewFriendsClient(authRefreshClient: AuthRefreshClient,
                                       preferencesInteractor: PreferencesInteractor): FriendsApiClient {

        val logger = run {
            val httpLoggingInterceptor = HttpLoggingInterceptor()
            httpLoggingInterceptor.apply {
                httpLoggingInterceptor.level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
            }
        }

        val okHttp = OkHttpClient.Builder().addInterceptor(logger).authenticator(RefreshUserAuthenticator(authRefreshClient, preferencesInteractor,
                UnauthorizedNavigator(SDKInternal.appContext, Interactors.preferences))).build()


        return Retrofit.Builder()
                .client(okHttp)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(MoshiConverterFactory.create())
                .baseUrl(Interactors.apiEndpoint)
                .build()
                .create(FriendsApiClient::class.java)


    }

Выдает ошибку

"Unable to create converter for class StickerDto"
Caused by NoJsonAdapter for java.util.Comparator<? super java.lang.String>

. Какой конвертер мне нужно использовать, если не тот конвертер Moshi? Попытка вытащить его как строку также дает ошибку, поскольку она ожидает и объект. Мне просто нужна эта строка.

Изменить, строка Json очень длинная, но начинается так:

{"tileId":"1264373a-24d8-4c10-ae90-d6e8f671410c","friendId":"2c50f187-039a-4f85-b12b-0c802396a611","name":"David Carey","message":"Joined WeAre8","animatedSticker":{"v":"5.5.7","fr":24,"ip":0,"op":48,"w":1024,"h":1024,"nm":"party_popper","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":3,"nm":"C | Position","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[176,892,0],"to":[-6.667,6.667,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":7,"s":[136,932,0],"to":[0,0,0],"ti":[-6.667,6.667,0]},{"t":11,"s":[176,892,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":7,"s":[115,75,100]},{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0]},"t":11,"s":[95,105,100]},{"t":20,"s":[100,100,100]}],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Controller","np":13,"mn":"Pseudo/DUIK controller","ix":1,"en":1,"ef":[{"ty":6,"nm":"Icon","mn":"Pseudo/DUIK controller-0001","ix":1,"v":0},{"ty":2,"nm":"Color","mn":"Pseudo/DUIK controller-0002","ix":2,"v":{"a":0,"k":[0.92549020052,0.0941176489,0.0941176489,1],"ix":2}},{"ty":3,"nm":"Position","mn":"Pseudo/DUIK controller-0003","ix":3,"v":{"a":0,"k":[0,0],"ix":3}},{"ty":0,"nm":"Size","mn":"Pseudo/DUIK controller-0004","ix":4,"v":{"a":0,"k":100,"ix":4}},{"ty":0,"nm":"Orientation","mn":"Pseudo/DUIK controller-0005

Ответы [ 3 ]

3 голосов
/ 18 июля 2020

Обратите внимание, что JsonObject - это класс из пакета gson, поэтому, если вы хотите использовать Moshi, вам нужно будет переключиться на JSONObject, который является классом по умолчанию, поддерживаемым Android.

To для этого вам нужно будет написать свой собственный адаптер JSONObject.

Сначала напишите свой класс адаптера:

import com.squareup.moshi.FromJson
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.ToJson
import okio.Buffer
import org.json.JSONException
import org.json.JSONObject

class JSONObjectAdapter {
    
    @FromJson
    fun fromJson(reader: JsonReader): JSONObject? {
        // Here we're expecting the JSON object, it is processed as Map<String, Any> by Moshi
        return (reader.readJsonValue() as? Map<String, Any>)?.let { data ->
            try {
                JSONObject(data)
            } catch (e: JSONException) {
                // Handle exception
                return null
            }
        }
    }
    
    @ToJson
    fun toJson(writer: JsonWriter, value: JSONObject?) {
        value?.let { writer.value(Buffer().writeUtf8(value.toString())) }
    }
}

Отрегулируйте вашу модифицированную сборку для предоставления настраиваемого объекта Moshi при создании MoshiConverterFactory:

    .addConverterFactory(MoshiConverterFactory.create(Moshi.Builder().add(JSONObjectAdapter()).build()))

, а затем вы можете go и использовать JSONObject

@Json(name = "stickerData") val stickerData: JSONObject

Удачи, и я надеюсь, что это поможет!

0 голосов
/ 19 июля 2020

Встроенные адаптеры типов для Moshi включают массивы, коллекции, списки, наборы и карты . Тип JsonObject не входит в состав самого Moshi , но в любом случае это будет расширенный Map<String, Any>, поэтому просто используйте Map вместо объекта.

@JsonClass(generateAdapter = true)
class Sticker(
        @Json(name = "name") val name: String,
        @Json(name = "id") val id: String,
        @Json(name = "stickerData") val stickerData: Map<String, Any>,
        var isSelected: Boolean = false
)

Значения также автоматически конвертируются. Таким образом, вы найдете там строки, списки или числа.

0 голосов
/ 13 июля 2020

Я сделал стикерData в Map и использовал GsonConverterFactory вместо Moshi.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...