JSON Serialization with relations
badayumut opened this issue · 4 comments
Is there an existing issue?
- I have searched existing issues
Build info
- objectbox version: [e.g. 2.3.1]
- Flutter/Dart version: [e.g. 3.1.0, see
flutter --version
ordart --version
] - Build OS: [e.g. Ubuntu 22.04 | Windows 11 | macOS 10.16 ]
- Deployment OS or device: [e.g. Android 14 | iOS 16.4 | Galaxy S23 ]
Steps to reproduce
I'm working on exporting the model to json and retrieving it, and I reviewed the example here. I tried to implement it to my own model in the same way. Simple parameters (String, int) in the model are saved in json, but I cannot extract relations. Is there something I missed?
I'm trying to transfer the model as it is with relations and get it back.
https://github.com/objectbox/objectbox-dart/blob/main/generator/integration-tests/part-partof/lib/json.dart
import 'package:json_annotation/json_annotation.dart';
import 'package:objectbox/objectbox.dart';
part 'example_model.g.dart';
@Entity()
@JsonSerializable()
class Book {
@Id()
int id = 0;
String content;
@_PersonRelToOneConverter()
final author = ToOne<Person>();
Book({
required this.content,
});
factory Book.fromJson(Map<String, dynamic> json) => _$BookFromJson(json);
Map<String, dynamic> toJson() => _$BookToJson(this);
}
@Entity()
@JsonSerializable()
class Person {
@Id()
int id = 0;
String name;
@_BookRelToManyConverter()
final books = ToMany<Book>();
Person({
required this.name,
});
factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);
Map<String, dynamic> toJson() => _$PersonToJson(this);
}
class _PersonRelToOneConverter
implements JsonConverter<ToOne<Person>, Map<String, dynamic>?> {
const _PersonRelToOneConverter();
@override
ToOne<Person> fromJson(Map<String, dynamic>? json) => ToOne<Person>(
target: json == null ? null : Person.fromJson(json));
@override
Map<String, dynamic>? toJson(ToOne<Person> rel) => rel.target?.toJson();
}
class _BookRelToManyConverter
implements JsonConverter<ToMany<Book>, List<Map<String, dynamic>>?> {
const _BookRelToManyConverter();
@override
ToMany<Book> fromJson(List<Map<String, dynamic>>? json) =>
ToMany<Book>(
items: json == null
? null
: json.map((e) => Book.fromJson(e)).toList());
@override
List<Map<String, dynamic>>? toJson(ToMany<Book> rel) =>
rel.map((Book obj) => obj.toJson()).toList();
}
Expected behavior
should be able to access relations after created from json
Actual behavior
relations missing after json serialization
Code
Person author = Person(name: "author");
Book book1 = Book(content: "content1")..author.target = author;
Book book2 = Book(content: "content2")..author.target = author;
Person person = Person(name: "person");
person.books.add(book1);
person.books.add(book2);
final book1FromJson = Book.fromJson(book1.toJson());
final personFromJson = Person.fromJson(person.toJson());
print(book1FromJson.author.target?.name); // null
print(personFromJson.books.length); // 0
Logs, stack traces
TODO Add relevant logs, a stack trace or crash report.
Logs
[Paste your logs here]
From what I can see the constructors of the classes you have given do not have parameters for the relation fields:
Book({
required this.content, // no parameter for author
});
Person({
required this.name, // no parameter for books
});
In any case, I would strongly recommend to use a different model for the database and the JSON serializer and map between them. It would avoid this issue and also make any future changes easier to handle.
Let me know if this resolves your issue!
I was about to update the issue with that the generated example_model.g.dart did not have the rel convertion methods. Anyway I couldn't make it work this way. So i implemented a custom map for to-from methods. I think it's the best way to it with more control. Thanks!