Search code examples
androidandroid-jetpack-composekotlin-multiplatformcompose-multiplatform

Pass object as json string in Compose multiplatform


I try to pass a object from a screen to another using Jetbrain Navigation Compose :

@Composable
fun DisneyApp(
    navController: NavHostController = rememberNavController()
) {
    NavHost(
        navController = navController,
        startDestination = HOME_ROUTE,
    ) {
        composable(route = HOME_ROUTE) {
            HomeScreen(onClick = { poster ->
                navController.navigate(
                    "${DETAIL_ROUTE}/${
                        Json.encodeToString(poster)
                    }"
                )
            })
        }
        composable(
            route = "${DETAIL_ROUTE}/{${DISNEY_KEY}}",
            arguments = listOf(
                navArgument(DISNEY_KEY) { type = NavType.StringType })
        ) { from ->
            from.arguments?.getString(DISNEY_KEY)?.let {
                DetailScreen(Json.decodeFromString<Poster>(it))
            }
        }
    }
}

I receive following exception when I click on an item to move to detail screen :

java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{ uri=android-app://androidx.navigation/detail/{"id":1,"name":"Toy Story 4","release":"2019","playtime":"1 h 40 min","description":"Toy Story 4 is a 2019 American computer-animated comedy film produced by Pixar Animation Studios for Walt Disney Pictures. It is the fourth installment in Pixar's Toy Story series and the sequel to Toy Story 3 (2010). It was directed by Josh Cooley (in his feature directorial debut) from a screenplay by Andrew Stanton and Stephany Folsom; the three also conceived the story alongside John Lasseter, Rashida Jones, Will McCormack, Valerie LaPointe, and Martin Hynes.[2] Tom Hanks, Tim Allen, Annie Potts, Joan Cusack, Wallace Shawn, John Ratzenberger, Estelle Harris, Blake Clark, Bonnie Hunt, Jeff Garlin, Kristen Schaal and Timothy Dalton reprise their character roles from the first three films. They are joined by Tony Hale, Keegan-Michael Key, Jordan Peele, Christina Hendricks, Keanu Reeves, and Ally Maki, who voice the new characters. The film also posthumously features Don Rickles, who appears through use of archived voice recordings.","plot":"Nine years earlier, following the events of Toy Story 2, Bo Peep and Woody attempt to rescue RC, Andy's remote-controlled car, from a rainstorm. Just as they finish the rescue, Woody watches as Bo is donated to a new owner, and considers going with her, but ultimately decides to remain with Andy. Years later, a teenage Andy donates them to Bonnie, a younger child, before he goes off to college. While the toys are grateful to have a new child, Woody struggles to adapt to an environment where he is not the favorite as he was with Andy, apparent when Bonnie takes Woody's sheriff badge and puts it on Jessie instead, not even bothering to give him a role during her playtime.","poster":"https://user-images.githubusercontent.com/24237865/75087934-5a53dc00-553e-11ea-94f1-494c1c68a574.jpg","gif":"https://media0.giphy.com/media/sgswHaZw5yklq/giphy.gif?cid=ecf05e473wd424bhp29tw5i4clg60djlvz4aridyzgxua96q&rid=giphy.gif&ct=g"} } cannot be found in the navigation graph ComposeNavGraph(0x0) startDestination={Destination(0x78d845ec) route=home}

I have tried this solution in compose using Gson library and it worked perfectly fine :

navController.navigate("${MainDestinations.TMDB_CAST_ROUTE}/${
                                    Uri.encode(
                                        gson.toJson(cast, object : TypeToken<List<Cast>>() {}.type)
                                    )
                                }"

As you I need to use Uri.encode in jvm envirorment, but that is not available in compose multiplatform. Is there any library that you have used to solve this issue? Did you try to pass an object as json string using Jetbrain Navigation Compose?


Solution

  • I used following library and it solved the problem : https://github.com/ethauvin/urlencoder

    navController.navigate("$DETAIL_ROUTE/${
                                UrlEncoderUtil.encode(Json.encodeToString(poster))
                            }"
                        )
    

    Here is a sample using Jetbrain Navigation Compose : https://github.com/alirezaeiii/Disney-Compose-Multiplatform