Hi,
I'm using json_serializable and generated code described in official Flutter docs: https://flutter.dev/docs/development/data-and-backend/json#serializing-json-using-code-generation-libraries.
How can I use json_serializable and mobx generated code together?
As far as I can tell, there's no way to combine code generators like that. You'll have to write the fromJSON constructors on your deserializable stores manually. There needs to be some way to namespace the generated files.
Is there any way to use mobx without abstract classes?
This works for us:
@JsonSerializable()
class UserInfo extends _ObservableUserInfo {
UserInfo();
factory UserInfo.fromJson(Map<String, dynamic> json) => _$UserInfoFromJson(json);
Map<String, dynamic> toJson() => _$UserInfoToJson(this);
}
class _ObservableUserInfo = UserInfoBase with _$_ObservableUserInfo;
abstract class UserInfoBase implements Store {
@observable String userName;
// etc.
}
The code generated by json_serializable in your_file.g.dart is
UserInfo _$UserInfoFromJson(Map<String, dynamic> json) {
return UserInfo()
..userName = json['userName'] as String;
}
which will conveniently call the setter on the _$_ObservableUserInfo mixin made by mobx-codegen:
@override
set userName(String value) {
_$userNameAtom.context.checkIfStateModificationsAreAllowed(_$userNameAtom);
super.userName = value;
_$userNameAtom.reportChanged();
}
Thanks @lynn. I'll give it a try.
Closing this issue for now
@lynn, how about making a little bit simpler by removing extra class assignment?
@JsonSerializable()
class UserInfo extends UserInfoBase with _$UserInfo {
UserInfo();
factory UserInfo.fromJson(Map<String, dynamic> json) => _$UserInfoFromJson(json);
Map<String, dynamic> toJson() => _$UserInfoToJson(this);
}
abstract class UserInfoBase implements Store {
@observable String userName;
// etc.
}
Unfortunately adding JsonSerializable and Generics to the mix it just doesn't work
I'm aware of https://github.com/mobxjs/mobx.dart/pull/119
Here's something i can't make it to work
If I remove Generics it works just fine
`
@JsonSerializable()
class Group
factory Group.fromJson(Map
Map
}
abstract class GroupBase
int id;
@JsonKey(fromJson: _typeFromJson, toJson: _typeToJson)
@observable
T type;
@observable
String lines;
GroupBase({this.id, this.lines, this.type});
}`
Has another made this work with ObservableList?
[SEVERE] json_serializable:json_serializable on lib/todo/todo_list.dart:
Error running JsonSerializableGenerator
Could not generate `fromJson` code for `todos`.
None of the provided `TypeHelper` instances support the defined type.
package:mobx_fun/todo/todo_list.dart:19:24
â•·
19 │ ObservableList<Todo> todos = ObservableList<Todo>();
│ ^^^^^
╵
For the ObservableList<T>, here is what I've done:
@JsonSerializable annotation to the TodoList and Todo classesObservableList<T>. This helps in fromJson/toJson conversions.@JsonSerializable()
class TodoList = _TodoList with _$TodoList;
abstract class _TodoList with Store {
@observable
@_ObservableListConverter()
ObservableList<Todo> todos = ObservableList<Todo>();
// ...
}
I've added this to the todos example. You can see the full code here.
I've also added a guide on JSON Serialization on the website.
I love that you added this code! It makes it far easier to do JSON serialization for mobx-based stores. And the codes on the main site drive it home. Thank you!
Some feedback:
Why the use of the leading underscore? Isn't _ObservableListConverter a type you want people to use and not to make it private (even if only in name)?
The name _ObservableListConverter is fairly vague -- convert into what? Could you make it more clear that it supports @JsonSerializable as part of the name, e.g. @ObservableListJsonConverter?
Do I have to make a separate annotation at all? Could it be an argument to @observerable instead that serves as a signal to the codegen to generate the support for JSON? Or even better, if I've got @JsonSerializable as an attribute on the containing class, can the code generator just generate the JSON support for the @observerable collection?
Is there similar support for Maps and Sets?
Thanks Chris!
json_annotations package. Here too, I'll need to dig in to see how I can add the support directly inside the the Observable collections. Might have to dig in more to understand the interface contract for json_annotations package.re: #1 -- are you generating the annotation type? If so, what if I have multiple lists? Won't the name collide?
re: #4 -- can you use the same technique for Maps and Sets that you use for Lists?
Ya, in the example there is only one of those so it works fine. If we have multiple, we could genericize the converter itself.
class _ObservableListJsonConverter<T>
implements JsonConverter<ObservableList<T>, List<Map<String, dynamic>>> { ... }
Do note that the type argument T will have to implement an interface that has fromJson and toJson converters.
Ya the same technique works for maps and sets. A set is serialized to an array (List) and a map is just an object (Map<String, dynamic>).
Would you show how to call fromJson using todo_list? I keep getting the error like "type 'List
I like the good old json_serializable and not this json_mapper, this works as expected with json_serializable
@JsonSerializable()
class Company extends _Company with _$Company {
Company({List<Employee> employees}) {
if (employees != null) this.employees = ObservableList.of(employees);
}
factory Company.fromJson(Map<String, dynamic> json) => _$CompanyFromJson(json);
Map<String, dynamic> toJson() => _$CompanyToJson(this);
}
abstract class _Company with Store {
ObservableList<Employee> employees;
}
@JsonSerializable()
class Employee extends _Employee with _$Employee {
Employee();
factory Employee.fromJson(Map<String, dynamic> json) => _$EmployeeFromJson(json);
Map<String, dynamic> toJson() => _$EmployeeToJson(this);
}
abstract class _Employee with Store {
@observable
String name;
}
I've also added a guide on JSON Serialization on the website.
Hi, seems like your site is down. Where can I read this guide?
I'd like to use json_serializable too, instead of this weird json_mapper. Guys put a lot of code pieces here. What is a correct way, after all?
You added the @_ObservableListConverter - have you added same attributes for ObservableMap/Set?
I managed to serialize MobX Store too, according to the last @ali80 answer.
There's a little error: the code above this.employees.addAll(employees); will not work, because a new ObservableList() is not created yet. The correct way is this.employees = ObservableList()..addAll(employees), or simpler, this.employees = ObservableList.of(employees)

I managed to serialize MobX Store too, according to the last @ali80 answer.
There's a little error: the code abovethis.employees.addAll(employees);will not work, because new ObservableMap() is not created yet. The correct way isthis.employees = ObservableList()..addAll(employees), or simpler,this.employees = ObservableList.of(employees)
yes, there was a bug, now fixed, thanks for mentioning it.
Most helpful comment
@lynn, how about making a little bit simpler by removing extra class assignment?