objectbox-dart
objectbox-dart copied to clipboard
Add support for property converters
Hi, I'm a relatively new ObjectBox user, so firstly let me say thanks for what looks like an awesome library 💪
I'm investigating how I might go about encoding custom types in my current application. I've seen this (closed) issue about supporting custom types https://github.com/objectbox/objectbox-dart/issues/93 and I've also seen the example Dart code in https://docs.objectbox.io/advanced/custom-types#convert-annotation-and-property-converter.
The problem is that the pattern suggested here isn't really scalable. It means a bunch of boilerplate to create a backing variable (which will be ignored by ObjectBox) and then creating a getter/setter that wraps around that variable. When I'm interacting with this object, it means there's another "variable" (dbXXX
) that could be interacted with (but should never be). Plus, all this boilerplate needs to be copied/pasted into every class that happens to embed the custom type we're trying to convert.
I guess what I'm seeking is something like the Kotlin/Java @Convert
annotation so that my classes are nice and clean, and I've got reusable converter classes. Is this something being considered?
Apologies if if the above sounds like it is negative... I don't intend it that way. Thanks again for an amazing library.
FWIW, it also makes it painful to use final
fields. eg. consider the following class:
@Entity()
class Blah {
int id;
final Map<String, String> map;
Blah(this.id, this.map);
String get dbMap {
return ''; // conversion code
}
set dbMap(String v) {
// conversion code
}
}
Because ObjectBox doesn't know how to convert a Map
, it has to use the default constructor, so the generated code for this looks like the following, which doesn't compile because there's no empty constructor.
objectFromFB: (Store store, ByteData fbData) {
final buffer = fb.BufferContext(fbData);
final rootOffset = buffer.derefObject(0);
final object = Blah()
..dbMap =
const fb.StringReader().vTableGet(buffer, rootOffset, 6, '');
Plus in set dbMap()
, I can't replace the value of the underlying map
variable (well, technically in this example I can update the contents of a Dart Map
in-place... however, there are loads of objects that you can't update the contents and need to replace the whole object. eg. Uri
)
Another (minor) nitpick is that now my code generation has a bunch of warnings it about Map
class that it is ignoring. I find that when we get into the habit of ignoring warnings like this, we also tend to start ignoring warnings that actually matter. I've found that I can at least suppress that warning by using Transient()
, however, again that's a bit more boilerplate.
You've promoted your case very well, thanks for going to the extent and no, absolutely not taken negatively.
I can definitely see your point and I don't think there's anything preventing us to support both in-class converters via getters/setters and a custom class (or an extension?) :+1:
Any news on this?
It would be definitely much more convenient if we would have some kind of property annotations that would allow for automatic conversion, similarly to Java and Kotlin @Convert
annotations.
Currently it's necessary to create backing fields, getter, and potentially setter like this (although in immutable examples I'd do it with copyWith
):
enum Role {
unknown,
author,
admin
}
@Entity()
class User {
User(this.id, this.roleEncoded);
final int id;
// The Role type is not supported by ObjectBox.
Role get role => RoleConverter.decodeFromString(roleEncoded);
final String roleEncoded;
}
class RoleConverter {
static Role decodeFromString(String role) {
...
}
}
I would be super happy to see API similar to this instead:
@Entity()
class User {
User(this.id, this.role);
final int id;
@RoleConverter()
final Role? role;
}
class RoleConverter extends ObjectboxConverter {
...
}
or
@Entity()
class User {
User(this.id, this.role);
final int id;
@Property(fromDb: RoleConverter.fromDb, toDb: RoleConverter.toDb) // or similar
final Role? role;
}
class RoleConverter {
...
}
Hello any progress on this?
@noob8boi We'll share updates when there are some. If you are interested in this, it helps us more to prioritize this by using thumbs up on the first comment!