How to serialize dynamic keys of a json with kotlinx - kotlin

I have a json with this kind of key:
...
"metaData": {
"date:create": "2019-11-13t15:42:02+01:00",
"date:modify": "2019-11-13t15:42:02+01:00",
"exif:ColorSpace": "1",
"exif:ExifImageLength": "1500",
"exif:ExifImageWidth": "1125",
"exif:ExifOffset": "38",
"exif:Orientation": "1",
"jpeg:colorspace": "2",
"jpeg:sampling-factor": "1x1,1x1,1x1"
},
...
All the keys in the metaData object are dynamic (not really but there's hundred of different keys) how can i serialize this object without having to create a class with all the possible keys.
This is my work:
#Serializable
data class Image(
val name: String? = null,
val uid: String,
val createdAt: String? = null,
val updatedAt: String? = null,
val metaData: MetaData? = null,
)
#Serializable
data class MetaData (
#SerialName("date:create")
val dateCreate: String,
#SerialName("date:modify")
val dateModify: String,
#SerialName("exif:ColorSpace")
val exifColorSpace: String,
#SerialName("exif:ExifImageLength")
val exifExifImageLength: String,
#SerialName("exif:ExifImageWidth")
val exifExifImageWidth: String,
#SerialName("exif:ExifOffset")
val exifExifOffset: String,
#SerialName("exif:Orientation")
val exifOrientation: String,
#SerialName("jpeg:colorspace")
val jpegColorspace: String,
#SerialName("jpeg:sampling-factor")
val jpegSamplingFactor: String
)

You can use a JSONObject to serialize dynamically the metadata. Your Metadata class is useless with this solution, your Image instance will have a JSONObject as metadata property :
data class Image(
val name: String? = null,
val uid: String,
val createdAt: String? = null,
val updatedAt: String? = null,
val metaData: JSONObject? = null,
)

Related

In Kotlin, are there graceful ways of passing values from one instance to another, which have the same name?

I have the following classes
class A(
val value1: String,
val value2: String,
val value3: String,
val value4: String,
val value5: String,
)
class B(
val value1: String,
val value2: String,
val value3: String,
val value4: String,
val value5: String,
) {
compaion object {
from(a: A) = B(
value1 = a.value1,
value2 = a.value2,
value3 = a.value3,
value4 = a.value4,
value5 = a.value5,
)
}
}
I write codes as follows when I want to create an instance of B from A
val a: A = getAFromSomewhere()
val b: B = B.from(a)
I have a lot of codes as above and It's very boring for me to write the factory method, 'from'. Is there any easy way of writing this kind of codes in Kotlin??
You might be interested in the MapStruct library.
https://mapstruct.org/
It helps map between two objects(DTO, Entity, etc..).
Code
In this example we want to map between a Person (Model) and a PersonDto (DTO).
data class Person(var firstName: String?, var lastName: String?, var phoneNumber: String?, var birthdate: LocalDate?)
data class PersonDto(var firstName: String?, var lastName: String?, var phone: String?, var birthdate: LocalDate?)
The MapStruct converter:
#Mapper
interface PersonConverter {
#Mapping(source = "phoneNumber", target = "phone")
fun convertToDto(person: Person) : PersonDto
#InheritInverseConfiguration
fun convertToModel(personDto: PersonDto) : Person
}
Usage:
val converter = Mappers.getMapper(PersonConverter::class.java) // or PersonConverterImpl()
val person = Person("Samuel", "Jackson", "0123 334466", LocalDate.of(1948, 12, 21))
val personDto = converter.convertToDto(person)
println(personDto)
val personModel = converter.convertToModel(personDto)
println(personModel)
From: https://github.com/mapstruct/mapstruct-examples/tree/master/mapstruct-kotlin

How to parse LinkedHashMap in moshi (kotlin)

I am trying to create a JSON adapter for the following json
{
"message": {
"affenpinscher": [],
"african": [],
"airedale": [],
"akita": [],
"appenzeller": [],
"australian": [
"shepherd"
]
},
"status": "success"
}
I have tried the following
#JsonClass(generateAdapter = true)
data class BreedList(
val message: HashMap<String,List<String>> = HashMap<String,List<String>>()
)
and
#JsonClass(generateAdapter = true)
data class BreedList(
val message: Breed
)
#JsonClass(generateAdapter = true)
data class Breed(
val breed: List<String>
)
But both scenarios give me the errors, is there a way to parse the following object, I need the key as well as the list from the response
There is no need to create a custom adapter.
To parse the JSON you posted:
data class Base (
#field:Json(name = "message")
val message : Message,
#field:Json(name = "status")
val status : String
)
data class Message (
#field:Json(name = "affenpinscher")
val affenpinscher : List<String>,
#field:Json(name = "african")
val african : List<String>,
#field:Json(name = "airedale")
val airedale : List<String>,
#field:Json(name = "akita")
val akita : List<String>,
#field:Json(name = "appenzeller")
val appenzeller : List<String>,
#field:Json(name = "australian")
val australian : List<String>
)
Note: instead of String you can use whatever data type you need or create custom classes like Message.

Create customise Data class model using Kotlin Koin

I'm new to Kotlin & understanding the concepts as I move. Stuck in creating one type of Data class model where the response json structure as shown below
data class SPLPlayer(
#field:Json(name ="id") val playerId: String?,
val type: String?,
#field:Json(name ="value") val currentValue: String?,
#field:Json(name ="Confirm_XI") val isIn_XI: Boolean = false,
#field:Json(name ="Matches") val totalMatchs: String?,
#field:Json(name ="Position") val position: String?,
#field:Json(name ="Skill") val skill: String?,
#field:Json(name ="skill_name") val skillName: String?,
val teamId: String?,
val name: String?, // other keys to refer Name_Full, short_name
#field:Json(name ="Bowling") val bowler: SPLBowler? = null,
#field:Json(name ="Batting") val batsmen: SPLBatsmen? = null
)
data class SPLTeamInfo (
**How to parse the Team object which is dictionary**
)
Thanks & appreciate to every reader. Looking forward for the solution.
You should be able to use your own deserializer by adding annotation to a setter #set:JsonDeserialize() and passing your own deserializer implementation.
along the lines of:
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.JsonDeserializer
.. rest of imports
// for a given simplified json string
val json: String = """{"teams":{"1":{"name":"foo"},"2":{"name":"bar"}}}"""
class MyDeserializer : JsonDeserializer<List<Team>> {
override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): List<Team>? {
// iterate over each json element and return list of parsed teams
}
}
data class JsonResp (
#set:JsonDeserialize(using = MyDeserializer::class)
var teams: List<Team>
)
data class Team (
var id: String, // this is going to be a team key
var name: String
)
Tried GitHub search with query #set:JsonDeserialize and it shows thousands of examples.

kotlin-room figure out how to save this field

I upload information to the Book class.
tableName = "Books_name" data class Books( // #Embedded // val additional_imgs: MutableList<String>, val adult: Int, val author: String, val bookmark: Int, val chapters: MutableList<Chapter>? = null, val chapters_total: Int, // #Embedded // val comments: MutableList<Comment>, autoGenerate = true val id: Int? = null, val img: String, val lang: String, val last_activity: Int, val n_chapters: Int, val publisher: String, val rating: String, val s_title: String, val status: String, val t_title: String, // val team: Int, val writer: String, val year: String )
Book has a class Chapter
//#Entity(tableName = "Books_name")
data class Chapter(
val can_read: Boolean,
// autoGenerate = true
val id_glavs_list: Int,
val new: Boolean,
val status: String,
val title: String
)
But after adding this class, an error appears. I was looking for information, but everywhere they say that this is corrected by cleaning the project. But it does not help. EROR:
Entities and Pojos must have a usable public constructor. You can have
an empty constructor or a constructor whose parameters match the
fields (by name and type). - java.util.List

kotlin default value in data class is aways zero [duplicate]

This question already has answers here:
Gson Deserialization with Kotlin, Initializer block not called
(2 answers)
Closed 4 years ago.
I've a simple data class of User
data class User(#PrimaryKey(autoGenerate = true) val id: Long, val _id: String, val name: String, val about: String,
val phoneNumber: String, val token: String,
val lastLogin: String, val avatarUrl: String, #Embedded val location: Location,
val emailId: String, val gender: Boolean, val timestamp: Long = System.currentTimeMillis())
As you can see the last parameter is val timestamp: Long = System.currentTimeMillis()
the response comes from network using retrofit and parsed using GSON
timestamp does not comes in a response json it's just extra field I need to do some logic. The problem is that value is always 0. It should be the current time stamp
This will do the trick,
data class User(#PrimaryKey(autoGenerate = true) val id: Long, val _id: String, val name: String, val about: String,
val phoneNumber: String, val token: String,
val lastLogin: String, val avatarUrl: String, #Embedded val location: Location,
val emailId: String, val gender: Boolean) {
var timestamp: Long = System.currentTimeMillis()
get() = if(field > 0) field else {
field = System.currentTimeMillis()
field
}
}