How to assign value from one data class to another data class - kotlin

I have two data class, and after I assign value to attribute in infoModel, I want assign them to infoArchiveModel which has the same fields, in this case, id, env, description and endpoint in infoArchiveModel should be same as those in infoModel , how can I do that?
data class infoModel(
#Id
val id: String = "",
val environment: String = "",
val description: String = "",
val endPoint: String = "",
)
data class infoArchiveModel(
#Id
val id: String = "",
val environment: String = "",
val description: String = "",
val endPoint: String = "",
val date: String = " "
)

A data class can also declare a secondary constructor, just like this:
data class infoArchiveModel(
#Id
val id: String = "",
val environment: String = "",
val description: String = "",
val endPoint: String = "",
val date: String = " "
) {
constructor(model: infoModel):
this (model.id, model.environment, model.description, model.endPoint)
}
//use this constructor
val model: infoModel = ...
val archiveModel = infoArchiveModel(model)
BTW, class names should always start with a capital case.

Related

How manage data classes with empty data in retrofit?

I want to send to the API only the data that I indicate in my data class.
data class UserRequestDTO(
val name: String = "",
val surname: String = ""
)
My empty class
val userDTO = UserRequestDTO()
MyService.getService().users()
My request
#POST("/vo/search")
fun users(
#Body userRequestDTO: UserRequestDTO
): Call<ResponseDTO>
But the following json is being sent:
{"name": "", "surname": ""}
How can I have a class in which I only send the data that I fill in? don't want any data to be sent, and if for example I fill in the name, I don't want the last name to be sent
Making them optional should result in not sending them:
data class UserRequestDTO(
val name: String? = null,
val surname: String? = null
)

No value passed for parameter 'info' in data class

I have a data class
data class TaxEngineModel(
#Id
val Id: String = "",
val environment: String = "",
val tDescription: String = "",
val EndPoint: String = "",
val Type: String = "",
val info: infoModel,
)
when I want to create an object, I got an error "No value passed for parameter 'info'", how to fix this issue?
val model = TaxEngineModel()
As the error hints: You must pass a value for info or make info nullable. You have default values for all other backfields in your class, but not for info.
Pass a value:
val model = TaxEngineModel(info = someInfoModel)
or make info nullable:
...
val Type: String = "",
val info: infoModel?, // you could optionally assign null as default here
)
or define a default value:
...
val Type: String = "",
val info: infoModel = someInfoModel, // you could maybe create InfoModel here?
)
However in the later case, you'd need a global constant or something else the constructor has access to.

How to define a no-argument constructor in Kotlin file with #Parcelize annotation [duplicate]

I have 10+ variables declared in Kotlin data class, and I would like to create an empty constructor for it like how we typically do in Java.
Data class:
data class Activity(
var updated_on: String,
var tags: List<String>,
var description: String,
var user_id: List<Int>,
var status_id: Int,
var title: String,
var created_at: String,
var data: HashMap<*, *>,
var id: Int,
var counts: LinkedTreeMap<*, *>,
)
Expected usage:
val activity = Activity();
activity.title = "New Computer"
sendToServer(activity)
But the data class requires all arguments to be passed while creating a constructor. How can we simplify this like the Java POJO class constructor?
val activity = Activity(null,null,null,null,null,"New Computer",null,null,null,null)
sendToServer(activity)
You have 2 options here:
Assign a default value to each primary constructor parameter:
data class Activity(
var updated_on: String = "",
var tags: List<String> = emptyList(),
var description: String = "",
var user_id: List<Int> = emptyList(),
var status_id: Int = -1,
var title: String = "",
var created_at: String = "",
var data: HashMap<*, *> = hashMapOf<Any, Any>(),
var id: Int = -1,
var counts: LinkedTreeMap<*, *> = LinkedTreeMap<Any, Any>()
)
Declare a secondary constructor that has no parameters:
data class Activity(
var updated_on: String,
var tags: List<String>,
var description: String,
var user_id: List<Int>,
var status_id: Int,
var title: String,
var created_at: String,
var data: HashMap<*, *>,
var id: Int,
var counts: LinkedTreeMap<*, *>
) {
constructor() : this("", emptyList(),
"", emptyList(), -1,
"", "", hashMapOf<Any, Any>(),
-1, LinkedTreeMap<Any, Any>()
)
}
If you don't rely on copy or equals of the Activity class or don't use the autogenerated data class methods at all you could use regular class like so:
class ActivityDto {
var updated_on: String = "",
var tags: List<String> = emptyList(),
var description: String = "",
var user_id: List<Int> = emptyList(),
var status_id: Int = -1,
var title: String = "",
var created_at: String = "",
var data: HashMap<*, *> = hashMapOf<Any, Any>(),
var id: Int = -1,
var counts: LinkedTreeMap<*, *> = LinkedTreeMap<Any, Any>()
}
Not every DTO needs to be a data class and vice versa. In fact in my experience I find data classes to be particularly useful in areas that involve some complex business logic.
If you give default values to all the fields - empty constructor is generated automatically by Kotlin.
data class User(var id: Long = -1,
var uniqueIdentifier: String? = null)
and you can simply call:
val user = User()
the modern answer for this should be using Kotlin's no-arg compiler plugin which creates a non argument construct code for classic apies more about here
simply you have to add the plugin class path in build.gradle project level
dependencies {
....
classpath "org.jetbrains.kotlin:kotlin-noarg:1.4.10"
....
}
then configure your annotation to generate the no-arg constructor
apply plugin: "kotlin-noarg"
noArg {
annotation("your.path.to.annotaion.NoArg")
invokeInitializers = true
}
then define your annotation file NoArg.kt
#Target(AnnotationTarget.CLASS)
#Retention(AnnotationRetention.SOURCE)
annotation class NoArg
finally in any data class you can simply use your own annotation
#NoArg
data class SomeClass( val datafield:Type , ... )
I used to create my own no-arg constructor as the accepted answer , which i got by search but then this plugin released or something and I found it way cleaner .
Along with #miensol answer, let me add some details:
If you want a Java-visible empty constructor using data classes, you need to define it explicitely.
Using default values + constructor specifier is quite easy:
data class Activity(
var updated_on: String = "",
var tags: List<String> = emptyList(),
var description: String = "",
var user_id: List<Int> = emptyList(),
var status_id: Int = -1,
var title: String = "",
var created_at: String = "",
var data: HashMap<*, *> = hashMapOf<Any, Any>(),
var id: Int = -1,
var counts: LinkedTreeMap<*, *> = LinkedTreeMap<Any, Any>()
) {
constructor() : this(title = "") // this constructor is an explicit
// "empty" constructor, as seen by Java.
}
This means that with this trick you can now serialize/deserialize this object with the standard Java serializers (Jackson, Gson etc).
If you give a default value to each primary constructor parameter:
data class Item(var id: String = "",
var title: String = "",
var condition: String = "",
var price: String = "",
var categoryId: String = "",
var make: String = "",
var model: String = "",
var year: String = "",
var bodyStyle: String = "",
var detail: String = "",
var latitude: Double = 0.0,
var longitude: Double = 0.0,
var listImages: List<String> = emptyList(),
var idSeller: String = "")
and from the class where the instances you can call it without arguments or with the arguments that you have that moment
var newItem = Item()
var newItem2 = Item(title = "exampleTitle",
condition = "exampleCondition",
price = "examplePrice",
categoryId = "exampleCategoryId")
Non-empty secondary constructor for data class in Kotlin:
data class ChemicalElement(var name: String,
var symbol: String,
var atomicNumber: Int,
var atomicWeight: Double,
var nobleMetal: Boolean?) {
constructor(): this("Silver", "Ag", 47, 107.8682, true)
}
fun main() {
var chemicalElement = ChemicalElement()
println("RESULT: ${chemicalElement.symbol} means ${chemicalElement.name}")
println(chemicalElement)
}
// RESULT: Ag means Silver
// ChemicalElement(name=Silver, symbol=Ag, atomicNumber=47,
// atomicWeight=107.8682, nobleMetal=true)
Empty secondary constructor for data class in Kotlin:
data class ChemicalElement(var name: String,
var symbol: String,
var atomicNumber: Int,
var atomicWeight: Double,
var nobleMetal: Boolean?) {
constructor(): this("", "", -1, 0.0, null)
}
fun main() {
var chemicalElement = ChemicalElement()
println(chemicalElement)
}
// ChemicalElement(name=, symbol=, atomicNumber=-1,
// atomicWeight=0.0, nobleMetal=null)
From the documentation
NOTE: On the JVM, if all of the parameters of the primary constructor
have default values, the compiler will generate an additional
parameterless constructor which will use the default values. This
makes it easier to use Kotlin with libraries such as Jackson or JPA
that create class instances through parameterless constructors.
I'd suggest to modify the primary constructor and add a default value to each parameter:
data class Activity(
var updated_on: String = "",
var tags: List<String> = emptyList(),
var description: String = "",
var user_id: List<Int> = emptyList(),
var status_id: Int = -1,
var title: String = "",
var created_at: String = "",
var data: HashMap<*, *> = hashMapOf<Any, Any>(),
var id: Int = -1,
var counts: LinkedTreeMap<*, *> = LinkedTreeMap<Any, Any>()
)
You can also make values nullable by adding ? and then you can assing null:
data class Activity(
var updated_on: String? = null,
var tags: List<String>? = null,
var description: String? = null,
var user_id: List<Int>? = null,
var status_id: Int? = null,
var title: String? = null,
var created_at: String? = null,
var data: HashMap<*, *>? = null,
var id: Int? = null,
var counts: LinkedTreeMap<*, *>? = null
)
In general, it is a good practice to avoid nullable objects - write the code in the way that we don't need to use them. Non-nullable objects are one of the advantages of Kotlin compared to Java. Therefore, the first option above is preferable.
Both options will give you the desired result:
val activity = Activity()
activity.title = "New Computer"
sendToServer(activity)

How to check existence of object in sublist in kotlin

How to verify the existence of sub-child object inside the parent object using kotlin
I am trying to find if the parent object (Module.kt) has an object of it's sub child list
Parent class : Module.kt
data class Module
(
var id: String? = ObjectId().toHexString(),
var name: String = "",
var description: String = " ",
var frames : MutableList<Frame> = mutableListOf<Frame>(),
var functions : MutableList<Function> = mutableListOf<Function>(),
var created_at: Date = Date(System.currentTimeMillis()),
var updated_at: Date = Date(System.currentTimeMillis())
)
Child class : Frame.kt
data class Frame (
var id: String? = ObjectId().toHexString(),
var name:String = "",
var level:String = "",
var moduleID:String = "",
var subFrames : MutableList<Frame> = mutableListOf()
)
Example : Cheking the existence of a submenu in the root menu
example image explanation
Use MutableMap instead
data class Module
(
var id: String? = ObjectId().toHexString(),
var name: String = "",
var description: String = " ",
var frames :MutableMap<String,Frame> = mutableMapOf(),
var functions : MutableList<Function> = mutableListOf<Function>(),
var created_at: Date = Date(System.currentTimeMillis()),
var updated_at: Date = Date(System.currentTimeMillis())
)
data class Frame (
var id: String? = ObjectId().toHexString(),
var name:String = "",
var level:String = "",
var moduleID:String = "",
var subFrames : MutableMap<String,Frame>? = mutableMapOf()
)
var module = Module()
module.frames["LAB"]?.subFrames?.get("CODE")?.subFrames?.get("HTML")?.name

Kotlin create object with params syntax

I have an object
class Person {
#JsonProperty("name")
var name: String? = null
#JsonProperty("id")
lateinit var id: String}
There is an only empty constructor and I want to create a person so I wrote:
val person = Person()
person.name = "someName"
person.id = "SomeId"
I'm pretty sure that there is a prettier syntax, something like
val person = Person {name = "someName" , id = "someId"}
but I can't find an example.
am I missing something? should I create a secondary constructor to use this syntax or is there another way?
Please check apply method.
Your code will be like this:
val person = Person().apply {name = "someName", id = "someId"}
Another way - you can change declaration of Person to (e.g. just change brackets, replace var to val and remove lateinit):
class Person (#JsonProperty("name") val name: String? = null,
#JsonProperty("id") val id: String )
Then you will able to do this:
val person = Person(name = "someName", id = "someId")
You can achieve it with the constructor parameter.
class Person(
#JsonProperty("name")
var name: String? = null,
#JsonProperty("id")
var id: String
)
val person = Person(name = "someName", id = "someId")
Another way is make your class and desired variables open to be overridden.
open class Person {
#JsonProperty("name")
open var name: String? = null
#JsonProperty("id")
open var id: String = ""
}
val person = object : Person() {
override var name: String? = "SomeName"
override var id = "SomeId"
}