Moshi - convert string to object - android

I can't figure out how to do this in kotlin. I want to convert this string, to an object array:
[
{mode=bus, line=381, line_name=381, direction=Waterloo, operator=CX, date=2019-10-16, expected_departure_date=2019-10-16, aimed_departure_time=20:11, expected_departure_time=20:13, best_departure_estimate=20:13, source=Countdown instant, dir=outbound, operator_name=ABELLIO LONDON LIMITED, id=https://transportapi.com/v3/uk/bus/route/CX/381/outbound/490010596E/2019-10-16/20:11/timetable.json?app_id=f56baf6a&app_key=6b0d065a1465ccbb6f32438f3d960803},
{mode=bus, line=381, line_name=381, direction=Waterloo, operator=CX, date=2019-10-16, expected_departure_date=2019-10-16, aimed_departure_time=20:33, expected_departure_time=20:34, best_departure_estimate=20:34, source=Countdown instant, dir=outbound, operator_name=ABELLIO LONDON LIMITED, id=https://transportapi.com/v3/uk/bus/route/CX/381/outbound/490010596E/2019-10-16/20:33/timetable.json?app_id=f56baf6a&app_key=6b0d065a1465ccbb6f32438f3d960803}
]
The object I want to convert it too:
#JsonClass(generateAdapter = true)
data class BusLive(val aimed_departure_time: String, val best_departure_estimate: String, val date: String, val dir: String,
val direction: String,
val expected_departure_date: String,
val expected_departure_time: String,
val id: String,
val line: String,
val line_name: String,
val mode: String,
val operator: String,
val operator_name: String,
val source: String
)
I've tried:
fun moshiConverter(test:String) : String {
val moshi = Moshi.Builder().build()
val type = Types.newParameterizedType(LiveBus::class.java, LiveBus::class.java)
val adapter:JsonAdapter<String> = moshi.adapter(type)
val a = adapter.toJson(test)
return a
}
And no joy :(

I hope what you posted as JSON as just an example. Because it is not valid JSON string.
To fix your example you have to change couple of lines:
val type = Types.newParameterizedType(LiveBus::class.java, LiveBus::class.java)
val adapter:JsonAdapter<String> = moshi.adapter(type)
to
val type = Types.newParameterizedType(List::class.java, LiveBus::class.java)
val adapter = moshi.adapter(type)

Related

Can't parse json correctly

need help in parsing this json file from this endpoint
http://ergast.com/api/f1/constructors
this is my data class
data class Teams(
val MRData: MRdata
){
data class MRdata(
val ConstructorTable: ConstructorsTable,
val limit: String,
val offset: String,
val series: String,
val total: String,
val url: String,
val xmlns: String
){
data class ConstructorsTable(
val Constructors: List<Constructor>?
) {
data class Constructor(
val constructorId: String?,
val name: String?,
val nationality: String?,
val url: String?
)
}
}
}
when i use Teams class as a return model it logs actual data but, when i try to return specific data like constructorID or nationality it returns null.

Parameter specified as non-null is null error in Room Database

Here is my entity class:
#Entity
data class User(
#PrimaryKey
#Json(name = "id") val userId: String,
#Json(name = "login") val userName: String,
#Json(name = "avatar_url") val userAvatar: String,
val profile: Profile? = null
) : Serializable
Here is my Profile data class
data class Profile(
val avatar_url: String,
val bio: String,
val blog: String,
val company: Any,
val created_at: String,
val email: Any,
val events_url: String,
val followers: Int,
val followers_url: String,
val following: Int,
val following_url: String,
val gists_url: String,
val gravatar_id: String,
val hireable: Boolean,
val html_url: String,
val id: Int,
val location: String,
val login: String,
val name: String,
val node_id: String,
val organizations_url: String,
val public_gists: Int,
val public_repos: Int,
val received_events_url: String,
val repos_url: String,
val site_admin: Boolean,
val starred_url: String,
val subscriptions_url: String,
val twitter_username: Any,
val type: String,
val updated_at: String,
val url: String
) : Serializable
but every time I try to insert data into the table I am getting the error, how can I insert null data object in table while using room database?
The issue here is that Room doesn't know how to insert attribute of type Profile to the table.
The simple solution would be to use a type converter. Something like the following:
class DatabaseConverters {
#TypeConverter
fun toProfile(profileJson: String): Profile? {
return <Create a Profile object out of a JSON string>
}
#TypeConverter
fun fromProfile(profile: Profile?): String {
return <JSON string representation of Profile object>
}
}
In your case - you can use "" (empty string) when Profile is null.
More info about converters: Here

How can I join three list in one object in Kotlin

I'm trying to join three object list in one object with kotlin. But I don't know how to do it...
Some help will be appreciate.
This is my data class:
data class User(
val address: Address,
val company: Company,
val email: String,
val id: Int,
val name: String,
val phone: String,
val username: String,
val website: String
)
data class Post(
val body: String,
val id: Int,
val title: String,
val userId: Int
)
data class Comment(
val body: String,
val email: String,
val id: Int,
val name: String,
val postId: Int
)
That I want to do is get one object like this if possible:
data class PostJoin(body: String, id: Int, title; String, user: User, comments: List<Comment>)
This is that I'm trying to do it, only can mix two objects but no how I want.
val postUsers = post.joinBy(users) { (post,user) -> post.userId == user.id }
.map { PostViewModel(post = it.first, user = it.second) }
private inline fun <T : Any, U : Any> List<T>.joinBy(collection: List<U>, filter: (Pair<T, U>) -> Boolean): List<Pair<T, List<U>>> = map { t ->
val filtered = collection.filter { filter(Pair(t, it)) }
Pair(t, filtered)
}
Something like this might work:
val posts: List<Post>
val users: List<User>
val comments: List<Comment>
// initialize lists
...
val joinedPosts = posts.fold(ArrayList<PostJoin>()) { joinedPosts, post ->
val postComments = comments.filter { it.postId == post.id }
val user = users.first { it.id == post.userId }
joinedPosts.add(PostJoin(post.body, post.id, post.title, user, postComments))
joinedPosts
}
Seems to work for me: Try it online!. Though I did give a pretty lazy input.

How to create constructor for data class in Kotlin Android?

How to create constructor for data class in Kotlin Android ?
data class EventItem(
#SerializedName("dateEvent")
val dateEvent: String,
#SerializedName("dateEventLocal")
val dateEventLocal: Any,
#SerializedName("idAwayTeam")
val idAwayTeam: String,
#SerializedName("idEvent")
val idEvent: String,
#SerializedName("idHomeTeam")
val idHomeTeam: String,
#SerializedName("idLeague")
val idLeague: String,
#SerializedName("idSoccerXML")
val idSoccerXML: String,
#SerializedName("intAwayScore")
val intAwayScore: Any,
#SerializedName("intAwayShots")
val intAwayShots: Any,
#SerializedName("intHomeScore")
val intHomeScore: Any,
#SerializedName("intHomeShots")
val intHomeShots: Any,
#SerializedName("intRound")
val intRound: String,
#SerializedName("intSpectators")
val intSpectators: Any,
#SerializedName("strAwayFormation")
val strAwayFormation: Any,
#SerializedName("strAwayGoalDetails")
val strAwayGoalDetails: String,
#SerializedName("strAwayLineupDefense")
val strAwayLineupDefense: String,
#SerializedName("strAwayLineupForward")
val strAwayLineupForward: String,
#SerializedName("strAwayLineupGoalkeeper")
val strAwayLineupGoalkeeper: String,
#SerializedName("strAwayLineupMidfield")
val strAwayLineupMidfield: String,
#SerializedName("strAwayLineupSubstitutes")
val strAwayLineupSubstitutes: String,
#SerializedName("strAwayRedCards")
val strAwayRedCards: String,
#SerializedName("strAwayTeam")
val strAwayTeam: String,
#SerializedName("strAwayYellowCards")
val strAwayYellowCards: String,
#SerializedName("strBanner")
val strBanner: Any,
#SerializedName("strCircuit")
val strCircuit: Any,
#SerializedName("strCity")
val strCity: Any,
#SerializedName("strCountry")
val strCountry: Any,
#SerializedName("strDate")
val strDate: String,
#SerializedName("strDescriptionEN")
val strDescriptionEN: Any,
#SerializedName("strEvent")
val strEvent: String,
#SerializedName("strEventAlternate")
val strEventAlternate: String,
#SerializedName("strFanart")
val strFanart: Any,
#SerializedName("strFilename")
val strFilename: String,
#SerializedName("strHomeFormation")
val strHomeFormation: Any,
#SerializedName("strHomeGoalDetails")
val strHomeGoalDetails: String,
#SerializedName("strHomeLineupDefense")
val strHomeLineupDefense: String,
#SerializedName("strHomeLineupForward")
val strHomeLineupForward: String,
#SerializedName("strHomeLineupGoalkeeper")
val strHomeLineupGoalkeeper: String,
#SerializedName("strHomeLineupMidfield")
val strHomeLineupMidfield: String,
#SerializedName("strHomeLineupSubstitutes")
val strHomeLineupSubstitutes: String,
#SerializedName("strHomeRedCards")
val strHomeRedCards: String,
#SerializedName("strHomeTeam")
val strHomeTeam: String,
#SerializedName("strHomeYellowCards")
val strHomeYellowCards: String,
#SerializedName("strLeague")
val strLeague: String,
#SerializedName("strLocked")
val strLocked: String,
#SerializedName("strMap")
val strMap: Any,
#SerializedName("strPoster")
val strPoster: Any,
#SerializedName("strResult")
val strResult: Any,
#SerializedName("strSeason")
val strSeason: String,
#SerializedName("strSport")
val strSport: String,
#SerializedName("strTVStation")
val strTVStation: Any,
#SerializedName("strThumb")
val strThumb: Any,
#SerializedName("strTime")
val strTime: String,
#SerializedName("strTimeLocal")
val strTimeLocal: String,
#SerializedName("strTweet1")
val strTweet1: Any,
#SerializedName("strTweet2")
val strTweet2: Any,
#SerializedName("strTweet3")
val strTweet3: Any,
#SerializedName("strVideo")
val strVideo: Any
) {
constructor(
idEvent: String,
strEvent: String,
strDate: String,
idHomeTeam: String,
strHomeTeam: String,
intHomeScore: Any,
idAwayTeam: String,
strAwayTeam: String,
intAwayScore: Any
) : this(idEvent, strEvent, strDate, idHomeTeam, strHomeTeam, intHomeScore, idAwayTeam, strAwayTeam, intAwayScore)
}
screenshot : https://i.stack.imgur.com/riGkU.png
How to create constructor for data class in Kotlin Android ?
i've try to create constructor. But, i get "There's a cycle in the delegation calls chain"
please, correct my code and tell me solution for it. . .
For a data class, the constructor defined in the class header is the primary constructor. It can't delegate to any other constructor in that class (though it can delegate to a superclass constructor).
However, you can define secondary constructors in the body of the class, as long as those delegate to the primary constructor. For example:
data class EventItem(val dateEvent: String) {
constructor(date: Date) : this(date.toString())
}
The problem in the code you've posted is that your secondary constructor is trying to delegate back to itself. You have to delegate to the primary constructor instead, and that means you need to be able to determine a value for all of the parameters missing from the secondary constructor.

getting weather results from json (kotlin android)

I'm trying to get some results from json but i have a problem.When i have only this line of code it works and i can get the temperature
var main: TemperatureData? = null
but i want also to get more values from my json so i insert this line of code
var weather: WeatherDataJson? = null
When i'm adding the second line it doesn't fetch any data(it even stops fetching the var main:... data)
This is my weather data class
class WeatherData {
var main: TemperatureData? = null
var weather: WeatherDataJson? = null
}
here is my interface class
interface ApiInterface {
#GET("data/2.5/weather?q=Prague")
fun getWeatherData(#Query("appid") appId: String)
: Call<WeatherData>
}
My TemperatureData class
data class TemperatureData(var temp: String)
And my WeatherDataJson class
data class WeatherDataJson(var description:String)
In my mainclass i have a function to show the json into my screen but i can't load the "var weather..."
Here is the function
private fun getTemperatureData(repository: Repository) {
repository.getApiInterface()
.getWeatherData("4cf7f6610d941a1ca7583f50e7e41ba3")
.enqueue(object : Callback<WeatherData> {
override fun onFailure(call: Call<WeatherData>?, t: Throwable?) {
t?.printStackTrace()
}
override fun onResponse(call: Call<WeatherData>?, response: Response<WeatherData>?) {
val weatherData: WeatherData? = response?.body()
weatherData?.let {
it.main?.let {
tempText.text = it.temp
}
it.weather?.let{
weatherTextFromApi.text=it.description
}
}
}
})
}
On the description is says unresolved reference description
If you use openweathermap api declare those data classes
data class WeatherData(
#SerializedName("coord") val coord: Coord,
#SerializedName("weather") val weather: List<Weather>,
#SerializedName("base") val base: String,
#SerializedName("main") val main: TemperatureData,
#SerializedName("visibility") val visibility: Int,
#SerializedName("wind") val wind: Wind,
#SerializedName("clouds") val clouds: Clouds,
#SerializedName("dt") val dt: Int,
#SerializedName("sys") val sys: Sys,
#SerializedName("id") val id: Int,
#SerializedName("name") val name: String,
#SerializedName("cod") val cod: Int
)
data class Sys(
#SerializedName("type") val type: Int,
#SerializedName("id") val id: Int,
#SerializedName("message") val message: Double,
#SerializedName("country") val country: String,
#SerializedName("sunrise") val sunrise: Int,
#SerializedName("sunset") val sunset: Int
)
data class Coord(
#SerializedName("lon") val lon: Double,
#SerializedName("lat") val lat: Double
)
data class TemperatureData(
#SerializedName("temp") val temp: Double,
#SerializedName("pressure") val pressure: Int,
#SerializedName("humidity") val humidity: Int,
#SerializedName("temp_min") val tempMin: Double,
#SerializedName("temp_max") val tempMax: Double
)
data class Weather(
#SerializedName("id") val id: Int,
#SerializedName("main") val main: String,
#SerializedName("description") val description: String,
#SerializedName("icon") val icon: String
)
data class Clouds(
#SerializedName("all") val all: Int
)
data class Wind(
#SerializedName("speed") val speed: Double,
#SerializedName("deg") val deg: Int
)
if you goal is get description from weather all you need will be
weatherData.weather.firstOrNull()?. description ?: ""
For getting url of icon
It is kind of tricky, you could get url from response but only url of icon.
val iconId = weatherData.weather.firstOrNull()?. description
val iconUrl = iconId?.let{"http://openweathermap.org/img/w/${it}.png"} ?: ""
After that you should use Glide library or Picasso for loading imageUrl to ImageView
See more about Glide here https://github.com/bumptech/glide
The server response from OpenWeatherMap is returning a JSON array, not a JSON object, for weather. Gson/Retrofit cannot automatically turn an array into a single Object, so you need to change your data class to hold a List (or use a custom Gson deserializer and manually grab the item you want from the array).
Example of what your top level class should be:
class WeatherData {
var main: TemperatureData? = null
var weather: List<WeatherDataJson>? = null
}

Categories

Resources