[FIXED] Die Arrayliste von Objekten aus der JSON-Zeichenfolge kann nicht mithilfe der Serialisierung in Kotlin decodiert werden

Ausgabe

Ich habe also eine ActorModel-Klasse, die eine Arraylist von MovieModel enthält. Ich habe versucht, es zu codieren und in einem Bündel an die nächste Aktivität zu senden. Allerdings heißt es:

kotlinx.serialization.json.internal.JsonDecodingException: Expected start of the object '{', but had 'EOF' instead at path: $
JSON input: kotlinx.serialization

Hier ist meine ActorModel-Klasse:

package com.sanjarbek.flixster2

import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.Serializable


@Serializable
data class ActorModel(
    val name: String,
    val popularity: String,
    val profile_path: String, ) {

    var movieModelArrayList: ArrayList<MovieModel> = ArrayList<MovieModel>()
        set(value) {field = value}
        get() = field

    fun mainMovie(): String {
        val json = Json.encodeToString<ArrayList<MovieModel>>(movieModelArrayList)
        return json
    }
    fun main(): String {
        val json = Json.encodeToString(ActorModel(name, popularity, profile_path))
        return json
    }
    }

gefolgt von der MovieModel-Klasse:

package com.sanjarbek.flixster2

import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.Serializable

@Serializable
data class MovieModel (
    private val original_title: String="",
    private val poster_path: String="",
    private val overview: String=""
) {

    fun get_title(): String{
        return original_title
     }

    fun get_image(): String{
        return poster_path
    }

    fun get_description(): String{
        return overview
    }

}

Hier ist der Code, bei dem ich versucht habe, ihn mit Bundle zu senden:

holder.image.setOnClickListener {
        val intent = Intent(context, ActorInfoActivity::class.java)
        intent.putExtra("image", image_url)
        intent.putExtra("name", model.name)
        intent.putExtra("model", model.main())
        context.startActivity(intent)
    }

Und wo ich es empfange und entschlüssele:

val actor = Json.decodeFromString<ActorModel>("kotlinx.serialization")
val movies = Json.decodeFromString<ArrayList<MovieModel>>("kotlinx.serialization")
Log.d("TAG", "onCreate: $actor"
Log.d("TAG", "onCreate: $movies")

Lösung

Wenn Ihre Frage lautet, wie Sie die oben beschriebenen Objekte an eine andere Aktivität übergeben können, ist hierfür kein JSON-Objekt erforderlich. Android gibt uns die Tools, um dies sofort zu tun. Ich habe deine Klassen etwas umgeschrieben:

SchauspielerModell

import android.os.Parcelable
import kotlinx.android.parcel.Parcelize

@Parcelize
data class ActorModel (
    val name: String,
    val popularity: String,
    val profilePath: String,
    var movieModelArrayList: MutableList<MovieModel> = mutableListOf()): Parcelable {

    override fun toString(): String {
        return "ActorModel(name=$name, popularity=$popularity, profilePath=$profilePath)\n" +
                "movieModelArrayList=$movieModelArrayList"
    }
}

MovieModel

import android.os.Parcelable
import kotlinx.android.parcel.Parcelize

@Parcelize
data class MovieModel (
    val original_title: String = "TestTitle",
    val poster_path: String = "./Test",
    val overview: String = "Test"
): Parcelable

I draw your attention to the @Parcelize annotation and interface Parcelable – this is the most important change to your code. Parcelable process is much faster than Serializable. One of the reasons for this is that we are being explicit about the serialization process instead of using reflection to infer it. In fact, we must manually implement the methods of the Parcelable interface. But the creators of Kotlin took care of us and added the @Parcelize annotation, which does all the dirty work for us. By default, it is not available, how to enable it is described in detail in the answer.

Sending data

import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class TestActivity: AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val actor = ActorModel("Alex", "10", "./profiles")
        actor.movieModelArrayList.add(MovieModel())

        val intent = Intent(this, MainActivity::class.java)
        val bundle = Bundle()
        bundle.putParcelable("actor", actor)
        intent.putExtras(bundle)

        startActivity(intent)
    }
}

Getting data

class MainActivity: AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val actor = intent.extras?.get("actor") as ActorModel
        Log.i("Test", actor)
    }
}

A small digression

In der MovieModelKlasse benötigen Sie keine Getter, da Sie die Felder bereits als val deklariert haben – sie sind nicht mehr änderbar und schreibgeschützt. Der private Modifikator macht also auch keinen Sinn. Es ist nicht mehr Java, entspannen Sie sich und genießen Sie Kotlin 🙂


Beantwortet von –
Olexandr Kisurin


Antwort geprüft von –
Mary Flores (FixError Volunteer)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like

[FIXED] String mit Array vergleichen

Ausgabe Ich möchte eine Zeichenfolge (Postleitzahl, zB: “50000”) mit einem Array von Zeichenfolgenelementen vergleichen, und wenn das Array…