How to make multiple constructor generic data Class in kotlin - kotlin

I want to use multple Constructors like this :
data class MyData<T>(
val code: String,
val message: String,
val data: T? = null,
) {
constructor(code: String, message: String) : this(code, message, null)
}
and I Use
MyData(code = "-1", message = "Support only application/json Content-Type") // Error : Not Enough Information To Infer Parameter T
MyData(code = "-1", message = "message", data = "data")
How to Use MyData property 'data' default value is 'null'?
( I want to MyData(code, message) not MyData(code, message) )

You pass the type like this:
val obj1 = MyData<String>(code = "-1", message = "Support only application/json Content-Type")
Note that data should probably be a var instead of a val, or you won't be able to change it.

Related

Android Serialization Jackson deserialize using JsonTypeInfo

Good morning. I'm trying to figure out how to deserialize a parameter but I can't find the solution. In practice, the response JSON should populate or not a field based on the value I get from another type of field, which is numeric and can be 0 or 1.
In particular (seeing following serialization) in MyData class there is a property called "mutable_value" that can be 1 or 0. when is 1 I must serialize b_property, else I must serialzie c_property.
I'm trying to achieve it but I don't know where I can do my case if 0 or 1...
The class I serialize is the following:
data class ClassResponseData(
#JsonProperty("code")
val code: String,
#JsonProperty("data")
val data: MyData,
) {
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
visible = true,
property = , // <-------------what I must do here?
defaultImpl = MyData.DefaultValue::class
)
#JsonSubTypes(
JsonSubTypes.Type(
value = MyData.BType::class,
name = "new_domain"
),
JsonSubTypes.Type(
value = MyData.CType::class,
name = "new_domain"
)
)
sealed class MyData{
data class DefaultValue(
#JsonProperty("b_value")
val bValue: String,
#JsonProperty("c_value")
val cValue: String,
#JsonProperty("mutable_value")
val mutableValue: Int
)
data class BType(
#JsonProperty("b_value")
val bValue: String,
#JsonProperty("mutable_value")
val mutableValue: Int
) : MyData()
data class CType(
#JsonProperty("c_value")
val cValue: String,
#JsonProperty("mutable_value")
val mutableValue: Int
) : MyData()
}
}
What I'm doing wrong?

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.

Moshi Retrofit Request

I'm doing a POST request and I'm using
#JsonClass(generateAdapter = true)
And the request body is as follow:
{
"request": "some data",
"data": {}
}
When creating my data class, how could I declare the empty object "data" = {}
My data class is as follow:
#JsonClass(generateAdapter = true)
data class Request(val request: String, val data: ?)
But, how could I create the empty body?
Your data should be nullable type of necessary class with 'null' default value, so like:
#JsonClass(generateAdapter = true)
data class Request(val request: String, val data: MyData? = null)
I think it will works.

Exclude non-null properties when serializing a Kotlin data class

I often will create a data class in Kotlin that is used internally for data models. Example:
data class MyDataModel(
var id: String? = null,
var ownerId: String,
var name: String,
var isPrivate: Boolean = false,
)
I often need to serialize these classes to JSON. The problem is that some of the class properties are not nullable and there are cases where I need to exclude those fields in the serialization. I haven't found a clean and simple way to do that. The solution I currently use is not to use non-nullable properties and then set those that I don't want serialized to null.
Is there another approach?
Solution using kotlinx.serialization:
Define class, including all fields you want to be serialized, mark it as #Serializable
#Serializable
open class MyDataModelSerializable(
open var id: String? = null
)
Make your data class to be its subtype:
data class MyDataModel(
var ownerId: String,
var name: String,
var isPrivate: Boolean = false,
override var id: String? = null
) : MyDataModelSerializable(id)
Serialize instances of MyDataModel class with serializer for MyDataModelSerializable:
val s = serializer<MyDataModelSerializable>()
println(Json.encodeToString(s, MyDataModel(ownerId = "1", name = "2", id = "3", isPrivate = true))) //{"id":"3"}
println(Json.encodeToString(s, MyDataModel(ownerId = "1", name = "2", isPrivate = true))) //{}
println(Json{encodeDefaults = true}.encodeToString(s, MyDataModel(ownerId = "1", name = "2"))) //{"id":null}

Not enough information to infer parameter T

Context: I am building a REST API with kotlin using Spring
Problem: I have a Kotlin class called Response that accepts a generic like this:
class Response<T> {
var data: T? = null
var dataArray: List<T>? = null
var errors: List<String>? = null
get() {
if (field == null) {
this.errors = ArrayList()
}
return field
}
}
When I try to instantiate in one of my API Controllers like this:
val response = Response()
response.setData(someting)
It gives me Not enough information to infer parameter T.
How can I avoid this error?
You will have to specify what T is in this case. Supposing it is a String, you could do it like this:
val response = Response<String>()
response.data = "Something that is a String"