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)
}
Related
I have a sealed class declared as follows:
sealed class SealedClass {
object Pizza: SealedClass()
data class Hamburger(val hasCheese: Boolean): SealedClass()
}
I have a map that maps SealedClass keys to String values and I would like to retrieve a particular string whenever I access the SealedClass.Pizza key within the map, but the result of accessing the SealedClass.Pizza entry returns null when I attempt to use a SealedClass.Pizza key that I construct in a different segment of my code.
The SealedClass.Pizza objects produced seem to have different hashes, which would probably explain why this is the case. Printing them results in
SealedClass$Pizza#4cf4ae53 and SealedClass$Pizza#21773412
I was under the impression that objects were the same across all instances of a class, so I don't know why they have different hashes, but regardless, I would like to be able to use both of these SealedClass.Pizza objects to access the same string. How might I do this?
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.
I learned from one example, so I am not sure if this is the optimal way or not, but anyways, I use the following code. I create one Retrofit instance and use it for all requests.
Since there are many methods, there are many types of data. It seems that I can create adapters (json -> my data class) automatically simply by adding annotations. But I needed more control (inheritance: the data classes have shared fields, dependency: some fields may not exist depending on other field's values), so I created a custom adaptor for each of the classes. So, currently my code is like this:
if (instance == null)
{
val gson = GsonBuilder()
.registerTypeAdapter(myClass1::class.java, myClassDeserialiser1())
.... (tens of this) ....
.registerTypeAdapter(myClass30::class.java, myClassDeserialiser30())
.create()
instance = Retrofit.Builder().
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
.create(MyAPIs::class.java);
}
return instance
The problem above is that I am creating instances of all parsers at the same time in advance. This may be inefficient. I wish I could create them when they are first needed. Is that possible?
You can add a #JsonAdapter annotation to your class definition in lieu of calling registerTypeAdapter. I can't comment on its efficiency, but it keeps the adapter info tied to the object instead of the creation of your Gson object, which sounds like what you want.
I've got a class that closely resembles one of my entities (I use the class for JSON de/serialization because the entity fails conversion to JSON, one of the known gotchyas of JSON + MVC).
Once I deserilize a JSON string into my object, is there a way to automatically update the associated Entity model instance. The property names are the same.
e.g.
'myDeserialized is the deserialized JSON object coming over the wire
Dim entityInstance As DLL.Person = db.getPersonById(myDeserialized.id)
myDeserialized.update(entityInstance)
Where this just goes through and takes all the properties in myDeserialized and updates the same named property in entityInstance?
Or is it possible to just iterate over a key-value pair of all the properties in an object/entity?
I'm looking for something like TryUpdateModel(), but that only works with forms, right? I don't want to tie my data to a form, that's all.
Thanks!
I don't know what type and version of EF you use, but there are very powerful functions for iterating on the entities properties. Which mean you can easily make your update function on the entity or its baseclass' partial (entityInstance.Update(myDesrialized)).
If you use EntityObject, then you can get an ObjectStateEntry for your entities and via this class you can very easily achieve this.
Please let us know what version and type of EF you use (POCO?)
When is it acceptable to do this. For example, I find myself sometimes needing to create, say, a form of tuple or something that has a key
so like a
String -> (myObj1, myObj2, myObj3)
I end up making a class to hold the myObj1 -> 3 but as you can see this class has limited fields so it seems like its a waste of a class as such.
Should I not worry about that or is it bad design to create classes for list storage purposes?
It depends on how complicated the list objects are. Most languages/frameworks have build in classes for tuples, pairs, key->value pairs, points, associative arrays and similar forms. If your objects are a little more complicated and can't find anything that fits your needs use a custom class. I don't see any problems here.
There are various options:
C# KeyValue: IList<KeyValuePair<string, string>>
C# Dictionaty: Dictionary<string, string>)
Java: Map<String, String>
Php associative arrays: $myVal = $myArray['$myKey']