Is there a way of serializing a `MutableList<Pa...
# announcements
r
Is there a way of serializing a
MutableList<Pair<Pair<String, Boolean>, Triple<String, String, Boolean>>>
type with the kotlinx serialization lib without writing a custom type converter?
Trying to insert this list in an Android room database
I've red the docs but seems like
.encodeToString()
won't work in this case
n
i don't know but it's a complex type wouldn't it make sense to create a dedicated class with a serializer for rhe sake of readability?
3
r
How would you approach this? The list is a week schedule, an item is like; monday, true/false, 09:00, 17:00, true/false
Just map it to a list of strings? Then you would loose index
j
I don’t know anything about kotlinx serialization, but by reading the type
MutableList<Pair<Pair<String, Boolean>, Triple<String, String, Boolean>>>
, or any code using it, there is absolutely no way of knowing what the list represents, what the pairs represent, what the strings and the booleans represent. Even with your example, it’s not quite easy to figure out. If you had a class
WeeklySchedule
, containing a collection (list, or map) of
Appointment
(I’m guessing here), containing a TimeInterval, and named boolean properties such as
booked
or
meetingPlanned
for example, all the code would be much easier to understand than things like
list[2].first.second
. Instead you could have
weeklyScheduled.get(TUESDAY).isBooked
. Your days shouldn’t be strings, but most probably a DayOfWeek enum instance. Your hours shouldn’t be strings but LocalTime instances. This would prevent you from storing incorrect values like “Satrday” or “25:62" in your objects.
1
n
I'm still not sure what each part of your complex type represents, but it seems like it could almost be represented simply by
List<Period>
. that captures all the "true" values, and each Period is an intra-day timerange already.
r
Thanks for the replies, its quite simple. It's: day/dayIsSelected, fromTime/untilTime/isFullDay
The UI might make it more clear.
j
So you have a WeeklySchedule. WeeklySchedule contains a list of 7 DailySchedule. A dailySchedule has a day of type DayOfWeek, and it also has a nullable TimeInterval. If the TimeInterval is null, it means the daily schedule is not selected. If it’s not null, it means it is selected. The TimeInterval contains a start and an end, both of type LocalTime. If start and end are both equal to 00:00, then it means the full day is checked. You can of course have variations (use a Map<DayOfWeek, DailySchedule> for example) depending on the context and what it could impose to the design, but anyway, having well-defined classes with well-named, well-typed properties and methods is way easier to understand and maintain than having pairs of pairs of triples.
r
Yes, I fully agree with you there. I will refactor my codewith your suggestion
Coming back to my initial question, how would you map this to a JSON and back?
m
I absolutely back Jean-Baptiste, your initial type suffers from Primitive Obsession. It would be best to write domain-specific types. As for JSON mapping , you have to annotate your classes and maybe write a custom serializer for non-primitive fields.
r
This is how I eventually solved it, think it's a big improvement:
Any feedback is welcome
m
Good refactoring! I have some suggestions if you want: • since the selection is part of the UI it shouldn’t be reflected by the model, so you could eliminate the
isSelected
and
dayOfWeek
properties, and restructure your time frame as a
Map<DayOfWeek, RuleDay>
: this way only the existing mappings are those selected • in
RuleDay
you could leave separated from/until time fields, or you could merge them in a
ClosedRange<LocalTime>
having only one property that will provide you facilities to check inclusion and boundaries • |--> a “full day” flag would be represented as a 0..23 range
r
Thanks for your elaborate suggestions. I'll take them in consideration. How do you evaluate the TypeConverters?
m
Sadly I don’t have enough experience on kotlinx.serialization to give you an advice, but in general it seems you are doing some unnecessary work to encode the values in a pipe-separated string which could be avoided relying only on JSON conversion