Confused about the following line #field:[Expose SerializedName("id")] - kotlin

I have the following data class that will retrieve data from an API:
data class Users(
#field:[Expose SerializedName("id")]
val id: Int)
I am just wondering what the #field: means.
Normally, I have always done like this:
data class Users(
#Expose
#SerializedName("id")
val id: Int)
I understand the meaning of expose and serializedName.
Just a few questions:
My best guess would be for the #field:[] would be to take an array of annotations, instead of putting them on each line as in the second example?
But is the field a Kotlin keyword or an annotation as it's preceded by the #?
Where else could you use the #field?

The val id in your example is declaring several different things in one go:
A constructor parameter.
A property of the class, implemented as a getter method.
A backing field for the property.
So which of those does an annotation get applied to?  It defaults to the parameter, and that's what your second example does.
If you want it to apply to the field instead, as in your first example, you use the field: target.
(It usually applies to single annotations, but it can apply to an array of them, as in this case.)
For more details, see the link jonrsharpe provided: https://kotlinlang.org/docs/reference/annotations.html#annotation-use-site-targets
The field:, property:, file:, &c targets are only for use with annotations.  (field is also a keyword within getter/setter definitions.)

Related

Kotlin - keeping a list of properties without repeating class name

In Kotlin, I keep a list of the names for a subset of the properties in class. Example:
listOf(
Car::model.name,
Car::make.name,
Car::company.name,
Car::year.name,
Car::power.name,
Car::cylinders.name,
Car::gearType.name,
Car::seats.name,
)
This can be shortened as follows, so that Car and .name are not repeated per list element.
with (Car()) {
listOf(
::model,
::make,
::company,
::year,
::power,
::cylinders,
::gearType,
::seats,
)
}.map { it.name }
I don't like this approach though, because it creates an object from the class. This may not be possible in all situations (private constructors, non-default constructor with many dependencies, or the object may be expensive to construct).
Is there a better solution?
You need to check why the it.name is needed. You're using a reflectional way to get the name of all/some fields. First of all you're having a reflective property element in your hands and then you just want to get the properties name.
If you want to shorten the mapping (+1 iteration) you can simply add .name already in the listOf() part.
Please notice that this is a very static way. If you want to have all fields OR/and properties you can use this as well:
Car::class.members // Members and Fields are different!!
Or you access the generated java class fields: Car::class.java.declaredFields and map it to list.
Shortest example for everything: Car::class.java.declaredFields.map{ it.name }

Kotlin: get members of a data class by reflection in the order they have been defined

Assume the following simple example data class:
data class SomeDataClass(
var id: String,
var name: String,
var deleted: String
)
With the following code it is possible to get the properties (and set or get their values):
import kotlin.reflect.full.memberProperties
val properties = SomeDataClass::class.memberProperties
print(properties.map { it.name }) // prints: [deleted, id, name]
The map within the print statement will return a List with the name of the properties in alphabetical order. I need the list in the order they have been defined in the source code, in this case: [id, name, deleted].
It doesn't seem achievable purely through reflection. The only solution I could come up with is to use a helper class defining the order:
val SomeDataClass_Order = listOf("id", "name", "deleted")
This wouldn't be a problem for one or two classes, but it is for hundreds of data classes with the largest one having up to almost one hundred properties.
Any idea would be welcome. I do not need detailed code, rather hints (like parsing the source code, annotations, etc).
If all the properties are declared in the primary constructor, you could "cheat":
val propertyNames = SomeDataClass::class.primaryConstructor!!.parameters.map { it.name }
If you want the KPropertys:
val properties = propertyNames.map { name ->
SomeDataClass::class.memberProperties.find { it.name == name }
}
This unfortunately doesn't find the properties that are declared in the class body.
I don't know about other platforms, but on Kotlin/JVM, the order in which the backing fields for the properties are generated in the class file is not specified, and a quick experiment finds that the order (at least for the version of kotlinc that I'm using right now), the order is the same as the declaration order. So in theory, you could read the class file of the data class, and find the fields. See this related answer for getting the methods in order. Alternatively, you can use Java reflection, which also doesn't guarantee any order to the returned fields, but "just so happens" to return them in declaration order:
// not guaranteed, might break in the future
val fields = SomeDataClass::class.java.declaredFields.toList()
If you do want to get the properties declared inside the class body in order too, I would suggest that you don't depend on the order at all.

Replacement for struct in Kotlin and how to store the data in the run time

I have to store and update the below variables in Kotlin
string name;
Array of Class Objects(5)
Array of Int(5)
C++ format:
struct subject
{
string name;
Array of Class Objects(5)
Array of Int(5)
};
vector<subject> sub;
In other programming languages C/C++ for ex, we use struct and put everything above in that.
Questions:
How to store and update above values with mixture of different types like Array, string, etc., in Kotlin?
Arrays will not get updated in one stretch. Ex: When someone calls AIDL interface with name, I create instance of class and stored the object in array of class obj(0) and integer array(0) as well updated with some value.
When the same AIDL interface is called with same name again, second instance of class will be created and store in **array of class obj(1)**and integer array(1) as well updated. As name is same, there is no need to update it again.
How to check the name and update the other arrays in the run time?
An additional use case, I need to make vector of that struct(according to C++). How I can achieve this in Kotlin?
Instead of a struct you would use a class in Kotlin: https://kotlinlang.org/docs/classes.html. There are several differences between the two that are relevant:
The declaration and class members and there implementation are done in the same place.
The constructor declaration is built into the class declaration.
Kotlin leans towards immutability. While you can reassign fields more often you will see val (like const) and immutable collections.
With that said, you would do something like this to implement your struct in Kotlin. The following isn't a literal 1 for 1 translation, but rather how you might solve your problem with idiomatic Kotlin:
class Subject(val name: String) {
val objects = mutableListOf<NameOfThatClass>()
val numbers = mutableListOf<Int>()
}
What's going on in that code snippet is that we are declaring a class Subject. It has a constructor that takes one argument called name of type String. The val keyword means that the argument will also be kept as a member variable, and that member variable cannot be reassigned. Next, in the class body, we declare and assign two more member variables. objects and numbers will also not be reassignable because of the val keyword, but instead of receiving a constructor argument as a value they receive the result of calling mutableListOf(), which creates more or less the equivalent of a vector. We could also use arrayOfNulls(5) and arrayOfInt(5), but unless you very specifically need fixed-sized arrays it's easier and more common to use lists in Kotlin.
You would then use it like so:
val myName = "foo"
val myFirstObject = ...
val myFirstNumber = 1
val mySubject = Subject(myName)
mySubject.objects += myFirstObject
mySubject.numbers += myFirstNumber
The += you see there isn't an actual reassignment, but an operator overload that acts as Kotlin's equivalent of std::vector's push_back(): https://kotlinlang.org/docs/collection-write.html#adding-elements.
Finally, as mentioned above, Kotlin's lists are what you would normally use in place of vector. However, it sounds like you want to be able to look up a specific entry by name, which is more efficient to do with a map https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-map/. You could do something like this:
val myMap = mutableMapOf<String, Subject>()
// add to the map like this
myMap[name] = Subject(name)
// get from the map like this (returns null if not in the map)
val mySubject = myMap[name]
// check if the subject is already in the map like this
myMap.containsKey(name)
Then, if you need to iterate over all the Subjects like you would with a vector, you can use myMap.values to get just the Subjects.

Recursively building a data class in Kotlin

I have am trying to create a recursive data class like so:
data class AttributeId (
val name: String,
val id: Int,
val children: List<AttributeId>?
)
The thing I'm struggling with now is building the data class by iterating over a source object.
How do I recursively build this object?? Is a data class the wrong solution here?
EDIT: Some more information about the Source object from which I want to construct my data class instance
The source object is a Java Stream that essentially* has the following shape:
public Category(final String value,
final Integer id,
final List<Category> children) {
this.value = value;
this.id = id;
this.children = children;
}
(For brevity the fields I don't care about have been removed from example)
I think I need to map over this stream and call a recursive function in order to construct the AttributeId data class, but my attempts seem to end in a stack overflow and a lot of confusion!
I don't think there's anything necessarily wrong with a data class that contains references to others.
There are certainly some gotchas.  For example:
If the list were mutable, or if its field was mutable (i.e. var rather than val), then you'd have to take care because its hashcode &c could change.
And if the chain of links could form a loop (i.e. you could follow the links and end up back at the original class), that could be very dangerous.  (E.g. calling a method such as toString() or hashCode() might either get stuck in an endless loop or crash the thread with a StackOverflowError.  You'd have to prevent that by overriding those methods to prevent them recursing.)  But that couldn't happen if the list and field were both immutable.
None of these issues are specific to data classes, though; a normal class could suffer the same issues (especially if you overrode methods like toString() or hashCode() without taking care).  So whether you make this a data class comes down to whether it feels like one: whether its primary purpose is to hold data, and/or whether the automatically-generated methods match how you want it to behave.
As Tenfour04 says, it depends what you're constructing these from.  If it naturally forms a tree structure, then this could be a good representation for it.
Obviously, you wouldn't be able to construct a parent before any of its children.  (In particular, the first instance you create would have to have either null or an empty list for its children.)  This would probably mean traversing the source in post-order.  The rest should fall out naturally from that.

Accessing properties of a Kotlin entity

I'm new to Kotlin, so apologies if I'm not articulating concepts correctly. I have an instance of an Entity
[TestEntity(applicationId=1, timestamp=2018-01-24T18:40:30, issueState=MA, product=test, status=sold, paymentMode=VISA, premium=null)]
I am writing a service that is going to take these keys and use them to create the headers of a report. The keys may change depending on the type of report the user is trying to generate, which will have an impact on the Entity that will be instantiated.
I want to be able to iterate over this Entity so that I can create an array to use for the headers. Any thoughts on how I do this?
I think the cleanest solution is storing values in a map and delegating properties to it.
Don't think you can otherwise iterate over class fields without some verbose getter chain or ugly reflection shenanigans.
For example here you can access map fields as if they were class fields, but can also easily iterate over map.
data class TestEntity(val map : Map<String, Any>){
val appId : Int by map
val timeStamp : Long by map
(... more fields)
}