hive icon indicating copy to clipboard operation
hive copied to clipboard

How to handle nullable values in custom TypeAdapter

Open TerryKingston opened this issue 3 years ago • 6 comments

Question How should a customer adapter handle potential null attribute values? I.e. I want to persist the null values when they are null:

Code sample

class MyObjectAdapter extends TypeAdapter<MyObject> {
  @override
  MyObject read(BinaryReader reader) {
    return MyObject(
        someIntAttribute: reader.readInt(), // <-- might be null but what bytes would actually be stored to represent null?
  }

  @override
  int get typeId => 1;

  @override
  void write(BinaryWriter writer, MyObject obj) {
    writer.writeInt(obj.someIntAttribute); // want to write something to represent null when someIntAttribute happens to be null
  }
}

TerryKingston avatar Sep 15 '20 01:09 TerryKingston

i think maybe you can use a special value, like the sentinel value: -1 or set default value

yyong37 avatar Sep 16 '20 09:09 yyong37

reader.readInt() will return 0.

image

As @rizzi37 said you can use a special value to represent null.

themisir avatar Sep 16 '20 12:09 themisir

why null values is not supported? using "special value" is not a solution

nailgilaziev avatar May 02 '22 15:05 nailgilaziev

why null values is not supported?

because it doesn't.

themisir avatar May 02 '22 20:05 themisir

maybe it should be done in future versions? )

nailgilaziev avatar May 03 '22 17:05 nailgilaziev

Well that's not my problem, it's this guy's mistake to introduce "special value" for nulls. And we're just following the convention. But for real it's not like we do not support writing null values.

checks notes..

So I totally missed what this conversation was about, but here's some conclusion: since dart does supports sound null safety and api design for our binary reader and writer is to not accept or return null values for writing/reading literals. If you need to represent a dynamic type (int or null) you can use write and read methods instead of readInt/writeInt to write values and hive will store type data alongside with value, so when reading it'll know that value is null or some other type and return value accordingly.

So to wrap things up write$Literal and read$Literal ($Literal = {byte, word, int, bool, ...}) doesn't supports null values because that's how they're designed to behave. They only write value itself, null isn't a value (or maybe it is, idk, it's implementation detail) but some weird thing we have to deal with, so those methods will not accept null as an argument or return it. But plain write and read methods do store additional byte alongside with values that represent its type which can be null as well, so you can use those methods to store nullable values.

I have no intention to modify api for existing methods because for me they're already explicit and null is an edge case you have to deal with, so you can either write additional byte to store whether or not the value is null or let hive do this by using read/write methods, or use magical values.

Hope this explains the situation. I would be interested in follow up replies if you have any further feedback to provide.

themisir avatar May 03 '22 21:05 themisir