Closed msxenon closed 2 years ago
It seems like it could almost work (with the new yet-unreleased support for final
fields), with the following declaration:
@freezed
class Person with _$Person {
@Entity()
factory Person({ @Id(assignable: true) int? id, String? name, int? age }) = _Person;
}
However, with the freezed
generated class being private (_$_Person
), it currently cannot be accessed from the objectbox.g.dart
. In order to support this, we'd need to switch generated code to use part/part of
. And because that would also be necessary if users wanted to store private fields, it might just make sense. Let's consider (the prep work) for 1.0.
I've had a look at what's available in the context when the generator runs... There doesn't seem to be any easy-to-get-to info whether the file is a library with parts or a single-file library, but there is file content so we can check manually - for each entity, the following should lead to the source file: element.enclosingElement.source
.
Therefore, we can do this post 1.0 without breaking compatibility for existing users. If others would like to see this feature, please upvote the original issue description (not this comment :) ).
freezed? frozen? Or shall we let grammar go...
freezed? frozen? Or shall we let grammar go...
That's the name of an existing package, not an annotation we'd add to ObjectBox. But yeah, I was a bit flabbergasted by the name myself...
freezed? frozen? Or shall we let grammar go...
:+1: Definitely! https://www.youtube.com/watch?v=L0MK7qz13bU
In the end, this didn't need to use part/part of
but only use the right type in the generated code. PR #255 adds support to do that, e.g.:
@freezed
class Person with _$Person {
@Entity(realClass: Person)
factory Person({ @Id(assignable: true) int? id, String? name, int? age }) = _Person;
}
@vaind I have the following freezed classes
// ignore_for_file: invalid_annotation_target
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:objectbox/objectbox.dart';
import 'currency.dart';
part 'user.freezed.dart';
part 'user.g.dart';
@freezed
class User with _$User {
@Entity(realClass: User)
factory User({
@Id(assignable: true) int? localId,
@Unique(onConflict: ConflictStrategy.replace) String? id,
@JsonKey(name: 'first_name') String? firstName,
@JsonKey(name: 'last_name') String? lastName,
@JsonKey(name: 'middle_name') String? middleName,
String? email,
String? username,
String? country,
@JsonKey(name: 'email_verified_at') String? emailVerifiedAt,
@JsonKey(name: 'phone_number') String? phoneNumber,
@JsonKey(name: 'phone_number_verified_at') String? phoneNumberVerifiedAt,
@JsonKey(name: 'google_id') String? googleId,
@JsonKey(name: 'facebook_id') String? facebookId,
@JsonKey(name: 'pin_set_at') String? pinSetAt,
@JsonKey(name: 'referral_code') String? referralCode,
@JsonKey(name: 'referred_by') String? referredBy,
@JsonKey(name: 'last_logged_in_at') String? lastLoggedInAt,
String? status,
@JsonKey(name: 'created_at') String? createdAt,
@JsonKey(name: 'updated_at') String? updatedAt,
ToOne<Currency>? currency,
}) = _User;
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:objectbox/objectbox.dart';
part 'currency.freezed.dart';
part 'currency.g.dart';
@freezed
class Currency with _$Currency {
@Entity(realClass: Currency)
factory Currency({
@Id(assignable: true) int? id,
String? code,
int? decimals,
String? name,
String? number,
String? symbol,
}) = _Currency;
factory Currency.fromJson(Map<String, dynamic> json) =>
_$CurrencyFromJson(json);
}
dart run build_runner build --delete-conflicting-outputs
fails with the following error
➜ dart run build_runner build --delete-conflicting-outputs
[INFO] Generating build script completed, took 630ms
[INFO] Reading cached asset graph completed, took 192ms
[INFO] Checking for updates since last build completed, took 717ms
[SEVERE] json_serializable:json_serializable on lib/src/models/account/user.dart:
Could not generate `fromJson` code for `currency`.
To support the type `ToOne` you can:
* Use `JsonConverter`
https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonConverter-class.html
* Use `JsonKey` fields `fromJson` and `toJson`
https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/fromJson.html
https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/toJson.html
package:test2/src/models/account/user.freezed.dart:510:26
╷
510 │ final ToOne<Currency>? currency;
│ ^^^^^^^^
╵
[INFO] Running build completed, took 6.2s
[INFO] Caching finalized dependency graph completed, took 47ms
[SEVERE] Failed after 6.3s
@Prn-Ice Have a look at our test code for an example using ToOne and ToMany with freezed: https://github.com/objectbox/objectbox-dart/blob/main/generator/integration-tests/part-partof/lib/frozen.dart
@vaind I have the following freezed classes
// ignore_for_file: invalid_annotation_target import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:objectbox/objectbox.dart'; import 'currency.dart'; part 'user.freezed.dart'; part 'user.g.dart'; @freezed class User with _$User { @Entity(realClass: User) factory User({ @Id(assignable: true) int? localId, @Unique(onConflict: ConflictStrategy.replace) String? id, @JsonKey(name: 'first_name') String? firstName, @JsonKey(name: 'last_name') String? lastName, @JsonKey(name: 'middle_name') String? middleName, String? email, String? username, String? country, @JsonKey(name: 'email_verified_at') String? emailVerifiedAt, @JsonKey(name: 'phone_number') String? phoneNumber, @JsonKey(name: 'phone_number_verified_at') String? phoneNumberVerifiedAt, @JsonKey(name: 'google_id') String? googleId, @JsonKey(name: 'facebook_id') String? facebookId, @JsonKey(name: 'pin_set_at') String? pinSetAt, @JsonKey(name: 'referral_code') String? referralCode, @JsonKey(name: 'referred_by') String? referredBy, @JsonKey(name: 'last_logged_in_at') String? lastLoggedInAt, String? status, @JsonKey(name: 'created_at') String? createdAt, @JsonKey(name: 'updated_at') String? updatedAt, ToOne<Currency>? currency, }) = _User; factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json); }
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:objectbox/objectbox.dart'; part 'currency.freezed.dart'; part 'currency.g.dart'; @freezed class Currency with _$Currency { @Entity(realClass: Currency) factory Currency({ @Id(assignable: true) int? id, String? code, int? decimals, String? name, String? number, String? symbol, }) = _Currency; factory Currency.fromJson(Map<String, dynamic> json) => _$CurrencyFromJson(json); }
dart run build_runner build --delete-conflicting-outputs
fails with the following error➜ dart run build_runner build --delete-conflicting-outputs [INFO] Generating build script completed, took 630ms [INFO] Reading cached asset graph completed, took 192ms [INFO] Checking for updates since last build completed, took 717ms [SEVERE] json_serializable:json_serializable on lib/src/models/account/user.dart: Could not generate `fromJson` code for `currency`. To support the type `ToOne` you can: * Use `JsonConverter` https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonConverter-class.html * Use `JsonKey` fields `fromJson` and `toJson` https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/fromJson.html https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/toJson.html package:test2/src/models/account/user.freezed.dart:510:26 ╷ 510 │ final ToOne<Currency>? currency; │ ^^^^^^^^ ╵ [INFO] Running build completed, took 6.2s [INFO] Caching finalized dependency graph completed, took 47ms [SEVERE] Failed after 6.3s
Any solution to this yet? Json serializable does not work well with ToOne & ToMany. Can you paste an example using json_serializable? Preferably with JsonConverter
Is this correct?
class AuthProviderSerializer implements JsonConverter<ToOne<AuthProvider>?, String?> {
const AuthProviderSerializer();
@override
ToOne<AuthProvider> fromJson(String? value) => ToOne(target: AuthProvider.valueOf('$value'));
@override
String? toJson(ToOne<AuthProvider>? instance) => instance?.target?.name;
}
There is also test code that uses json_serializable: https://github.com/objectbox/objectbox-dart/blob/main/generator/integration-tests/part-partof/lib/json.dart It creates a JsonSerializer for each ToOne/ToMany that uses the special constructors of ToOne and ToMany.
And your example looks almost right, it probably should handle the null case for fromJson
.
Hello, as far as I know in objectbox-dart we can't create an immutable class.
I have used
@freezed
with "HiveDB" but I wish we can achieve that with object boxExample:
edit by @vaind: fix the code block