Can't deserialize to pojo class (Kotlin) (RestAssured) - kotlin

**Hello! Here is the request to the server **
var stories: Story? =
given().log().all()
.contentType(ContentType.JSON)
.body(body)
.`when`().log().all()
.post(baseURI)
.then().log().all()
.extract().`as`(Story::class.java)
println (Story().title)
println (Story().id)
println (Story().items)
Here is POJO class
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
#JsonIgnoreProperties(ignoreUnknown = true)
class Data {
var stories: String? = null
}
class Story() {
var id = 0
var title: String? = null
var description: String? = null
var imageUrl: String? = null
var imageUrlEco: String? = null
var images: String? = null
var style: String? = null
var styleWeb: String? = null
var link: String? = null
var linkWeb: String? = null
var linkEco: String? = null
var buttonText: String? = null
var dateFrom: String? = null
var dateTo: String? = null
var hidden: String? = null
var isAuth: String? = null
var onboardingType: String? = null
var sortOrder = 0
var type: String? = null
var items: String? = null
}
class Item {
var id = 0
var title: String? = null
var description: String? = null
var detailedDescription: String? = null
var imageUrl: String? = null
var imageUrlWeb: String? = null
var style: String? = null
var styleWeb: String? = null
var sortOrder = 0
}
**And here is the response itself **
{
"data": {
"stories": \[
{
"id": 1234,
"title": "AnyText",
"description": "AnyText",
"imageUrl": "AnyText",
"imageUrlEco": AnyText,
"images": \[
],
"style": "AnyText",
"styleWeb": "AnyText",
"link": AnyText,
"linkWeb": AnyText,
"linkEco": AnyText,
"buttonText": "AnyText",
"dateFrom": "2022-11-22T00:00:00Z",
"dateTo": "2023-01-08T00:00:00Z",
"hidden": AnyText,
"isAuth": AnyText,
"onboardingType": AnyText,
"sortOrder": 1234,
"type": "AnyText",
"items": [
{
"id": 1234,
"title": "AnyText",
"description": "AnyText",
"detailedDescription": "AnyText",
"imageUrl": "AnyText",
"imageUrlWeb": "AnyText",
"style": "AnyText",
"styleWeb": "AnyText",
"sortOrder": 1
}
]
}
]
}
}
So when I try this:
println (Story().title)
println (Story().id)
println (Story().items)
The result of running the program is:
null
0
null
What I did wrong?

I have not used RestAssured so I cannot comment on the syntax/correctness of that, but your error is incorrectly referencing the object you have deserialized from the GET request.
var stories: Story? =
this means assign the result to a variable named stories
Later you write
println (Story().title)
what this means it print the field title from a brand new Story object. You should be doing this:
println (stories.title)
println (stories.id)
println (stories.items)
(stories should be named story if it represents one)

Related

How to fetch the particular field value from response body

This is the response body of post method
"body":
{
"id": 538,
"Fname": "abc",
"Lname": "Xyz",
"Type": {
"Type": "tryrtyr",
"createdBy": "ytyryr",
"createdDate": "2022-07-22T09:24:37.616+00:00",
"lastModifiedBy": "rtyryry",
"lastModifiedDate": "2022-07-22T09:24:37.616+00:00"
}
}
I tried to fetch the Id value but it is showing null value.
Fname, Lname are passing from excel file.
String jsonString = response.asString();
jsonString = response.asString();
List<Map<String, Object>> body = JsonPath.from(jsonString).get("");
Object Id = null;
for (Map<String, Object> item: body) {
if (item.get("Fname").toString().equals(Fname) &&
item.get("Lname").toString().equals(Lname)); {
Id = Integer.parseInt(item.get("id").toString());
}
}
System.out.println(Id);
Since the body is json object, not array, so you don't need a List here. I think you just need.
int id = response.jsonpath().getInt("id");

Ktor handle empty response for arrays

I have recently started using Ktor and got stuck at the very beginning itself.
I have a very simple response, which could have content like below -
{
"result": true,
"data": [
{
"Name": "Danish",
"Credit": "80"
},
{
"Name": "Kumar",
"Credit": "310"
}
]
}
Or it could be like this -
{
"result": false,
"data": [],
"message": "No data available, use default user",
"default": [
{
"Name": "Default User",
"Credit": "100"
}
]
}
And my response class is like -
#Serializable
data class UserResponse(
#SerialName("result") var result: Boolean? = null,
#SerialName("data") var data: ArrayList<User?>? = null,
#SerialName("message") var message: String? = null,
#SerialName("default") var default: ArrayList<User?>? = null
)
#Serializable
data class UserResponse(
#SerialName("Name") var name: String? = null,
#SerialName("Credit") var credit: String? = null,
)
io.ktor.client.call.NoTransformationFoundException: No transformation found: class io.ktor.utils.io.ByteBufferChannel
And I am getting NoTransformationFoundException, I think it could be due to data object being empty, but how to fix this?
According to this, we can catch this exception, but I can't use this as I need other data to be used.
Exception looks like you haven't install Json content negotiation plugin, when creating ktor client. It should be like this:
val httpClient = HttpClient {
install(ContentNegotiation) {
json()
}
}
Then you can use this client like this:
val response: UserResponse = httpClient.get("URL").body()

How to make GroupBy result list to new Map in Webflux

How to make GroupBy result list to new Map in Webflux
There is my input list and expect result. then what should I do to make the result.
// expect
{
"timestamp": "2019-06-13T00:00:00.000",
"result": {
"first": 1,
"second": 2,
"third": 3
}
}
// input list
[
{
"timestamp": "2019-06-13T00:00:00.000",
"first": 1
},
{
"timestamp": "2019-06-13T00:00:00.000",
"second": 2
},
{
"timestamp": "2019-06-13T00:00:00.000",
"third": 3
}
]
val Flux.fromIterable(list)
.groupBy{it.timestamp}
.concatMap { groupItem ->
// here!! I want to make `group by result list to new Map``
Result(timestamp = groupItem.key()!!, Item(first = ?, second = ?, third =?))
}
I figured it out.
Flux.merge(first, second, thrid)
.groupBy { it.timestamp }
.concatMap {
it.map { item ->
val container = mutableMapOf<String, Any>()
if (item is firstEntity) {
container["first"] = item.result.count
container["timestamp"] = it.key()!!
}
if (item is secondEntity) container["second"] = item.result.count
if (item is thridEntity) container["thrid"] = item.result.count
container
}.reduce { acc, current ->
acc.putAll(current)
acc
}
}
.map {
val first = (it["first"] ?: 0) as Int
val second = (it["second"] ?: 0) as Int
val thrid = (it["thrid"] ?: 0) as Int
val timestamp = (it["timestamp"] ?: "") as String
// somthing!!
}

get array from inside many objects in kotlin

l am try to build simple app provide flight schedule . the problem is l have many object in json url and the array list inside of these object and l cant to get array list from objects because l got error fatal Caused by: org.json.JSONException: Value
my data json api
{
"result": {
"response": {
"airport": {
"pluginData": {
"schedule": {
"arrivals": {
"data": [
{
"flight": {
"identification": {
"id": null,
"row": 4832637003,
"number": {
"default": "ZP4801",
"alternative": null
},
"callsign": null,
"codeshare": null
}
}
}
]
}
}
}
}
}
}
}
my code for getting data json of array list
private fun handleJson (jsonString: String?){
val jsonArray = JSONArray(jsonString)
val list = ArrayList<FlightShdu>()
var x = 0
while (x < jsonArray.length()){
val jsonObject = jsonArray.getJSONObject(x)
list.add(FlightShdu(
jsonObject.getInt("id"),
jsonObject.getString("callsign")
))
x++
}
val adapter = ListAdapte(this#MainActivity,list)
flightShdu_list.adapter = adapter
}
I would normally suggest for a full structure of the JSON via data classes, as this methodology could potentially be expensive to run multiple times over and over... The following highlights a method to dig into the JSON through jsonObjects by name, and then take the final layer of "identification" and populates a data class that is serializable with the resulting object
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.json.JsonDecodingException
import kotlinx.serialization.json.JsonElement
val data =
"""
{
"result": {
"response": {
"airport": {
"pluginData": {
"schedule": {
"arrivals": {
"data": [{
"flight": {
"identification": {
"id": null,
"row": 4832637003,
"number": {
"default": "ZP4801",
"alternative": null
},
"callsign": null,
"codeshare": null
}
}
}]
}
}
}
}
}
}
}
"""
#Serializable
data class FlightIdentification(
val id: Int?,
val row: String,
val number: IdentificationNumber,
val callsign: String?,
val codeshare: String?
) {
#Serializable
data class IdentificationNumber(
val default: String,
val alternative: String?
)
}
val json = Json(JsonConfiguration.Stable)
fun JsonElement?.get(name: String): JsonElement? {
return if (this == null) null
else this.jsonObject[name]
}
fun handleJson(jsonString: String) {
val obj = json.parseJson(jsonString)
val data = obj.get("result").get("response").get("airport").get("pluginData")
.get("schedule").get("arrivals").get("data")
if (data != null) {
val flight = data.jsonArray[0]
.get("flight").get("identification")
try {
val res = json.parse(FlightIdentification.serializer(), flight.toString())
println(res)
} catch (e: JsonDecodingException) {
println("Decode: ${e.message}")
}
}
}
handleJson(data)

How to parse below Json data in Kotlin?

I need to parse this information-
[
{
"artist": "12",
"image": "23"
},
{
"video_id": "12",
"video_title": "23"
},
{
"video_id": "12",
"video_title": "23"
},
{
"video_id": "12",
"video_title": "23"
},
{
"video_id": "12",
"video_title": "23"
},
{
"video_id": "12",
"video_title": "23"
}]
As you can see the first field is different, how to parse below information differently and the first field differently in Kotlin.
I am parsing 1st part as-
response ->
for (i in 0..(response.length() -1)){
/**
FIRST SONG
**/
val song = response.get(0).toString()
val listOfSongs = response.toString()
val parser = Parser()
val stringBuilder = StringBuilder(song)
val json: JsonObject = parser.parse(stringBuilder) as JsonObject
val firstArtist = json.string("artist")
val firstImage = json.string("image")
val intent = Intent(activity,ResultPage::class.java)
intent.putExtra("firstArtist",firstArtist)
intent.putExtra("firstImage",firstImage)
startActivity(intent)
/**
FIRST SONG
**/
}
}
and am also using KLAXON library here.
For your json, this should work :
fun parseResponse(response: String) {
var artist = ""
var image = ""
val videoList = ArrayList<Video>()
val jsonArray = JSONArray(response)
(0..5).forEach { index ->
val jsonObject = jsonArray.getJSONObject(index)
if (jsonObject.has("artist") && jsonObject.has("image")) {
artist = jsonObject.getString("artist")
image = jsonObject.getString("image")
}
else if (jsonObject.has("video_id") && jsonObject.has("video_title")) {
val newVideo = Video(jsonObject.getString("video_id"), jsonObject.getString("video_title"))
videoList.add(newVideo)
}
}
}
class Video(val id: String, val title: String)
But this way is very lengthy and unnecessary. I would suggest use an Object Mapping library like GSON or Moshi.
For that, the video list in your json should ideally be something like:
[
{
"artist": "12",
"image": "23",
"videos": [
{
"video_id": "12",
"video_title": "23"
},
{
"video_id": "12",
"video_title": "23"
},
{
"video_id": "12",
"video_title": "23"
},
{
"video_id": "12",
"video_title": "23"
},
{
"video_id": "12",
"video_title": "23"
}
]
}
]
Using this Json, you can easily create a class for this object, e.g.
class Artist(val id: String, val name: String, val image: String, val videos: List<Video>)
class Video(#field:Json(name = "video_id") val id: String, #field:Json(name = "video_title") val title: String)
And parse them easily like this:
Moshi.Builder().build().adapter(Artist::class.java).fromJson(response)
and then access this information like:
val artist = Moshi.Builder().build().adapter(Artist::class.java).fromJson(response)
intent.putExtra("firstArtist",artist?.name)
intent.putExtra("firstImage",artist?.image)
You can use below code to parse given json in kotlin
private fun parseJson(jsonResponse: String){
val jsonArray = JSONArray(jsonResponse)
for (i in 0..jsonArray!!.length() - 1) {
val jsonObj = jsonArray.optJSONObject(i)
val artist =jsonObj.optString("artist")
val image =jsonObj.optString("image")
val videosArray = jsonObj.optJSONArray("videos")
for (i in 0..videosArray!!.length() - 1) {
val videoObj = jsonArray.optJSONObject(i)
val video_id =videoObj.optString("video_id")
val video_title =videoObj.optString("video_title")
}
}
}