Encoding to a standard, colon-seperated json in dart/flutter and built_value - flutter

In my flutter project, I want to use built_value for json serialization. One of the sample classes is:
import 'dart:convert';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
part 'device.model.g.dart';
abstract class Device implements Resource, Built<Device, DeviceBuilder> {
// Fields
String get name;
String get code;
bool get isActive;
Device._();
factory Device([void Function(DeviceBuilder) updates]) = _$Device;
String toJson() {
return json.encode(serializers.serializeWith(Device.serializer, this));
}
factory Device.fromJson(String jsonString) {
return serializers.deserializeWith(
Device.serializer, json.decode(jsonString))!;
}
static Serializer<Device> get serializer => _$deviceSerializer;
}
I used the build_runner to generate the codes and everything is OK.
Also I have defined the serializers:
part 'serializers.g.dart';
final standardSerializers =
(serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();
#SerializersFor([
Device])
final Serializers serializers = _$serializers;
Now I want to use the toJson() method:
final device = Device((d) => d
..code = "DEV11"
..name = "Some Tools"
..isActive = true);
print(device.toJson());
The output is:
["name","Some Tools","code","DEV11","isActive",true]
which is a List of objects, instead of Map<String, dynamic>. The generated serializer is:
Iterable<Object?> serialize(Serializers serializers, Device object,
{FullType specifiedType = FullType.unspecified})
...
which returns an Iterable of Object?.
How can I make built_value to generate a json with the standard format, i.e:
{"name":"Some Tools","code":"DEV11","isActive":true};
P.S: using the dart encoder,
print(json.encode(device));
results in:
"[\"name\",\"Some Tools\",\"code\",\"DEV11\",\"isActive\",true]"

I made a silly mistake. Should be:
#SerializersFor([
Device,
])
final Serializers serializers =
(_$serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();

Related

Flutter dart replace replace Json object with variables

In this case I have class. Where I took a variable. Also I have a Json map. So I want to change Json map object replace with variables. Here is my code example....
So how can I achieve that
I want replace Json object with dart variable
class Data {
late String slug;
Map<String, String> singleProductVariable = {"slug": "$slug"};
}
Firstly, there is no JSON in your code sample.
I assume that you would like to set the value of the corresponding key in your Map when setting the variable.
If so, you might want to use a setter in a next way:
class Data {
String _slug;
late Map<String, String> v = {"slug": _slug};
Data(String slug) : _slug = slug;
set slug(String str) => v['slug'] = str;
}
void main() {
final d = Data("slug");
print(d.v);
d.slug = "newSlug";
print(d.v);
}
The output of the code above will be:
{slug: val}
{slug: newVal}

How to serialize private fields in json-serializable?

Minimal reproducible code:
#JsonSerializable()
class A {
final int _x;
A(int x) : _x = x;
factory A.fromJson(Map<String, dynamic> json) => _$AFromJson(json);
}
Note:
I don't want to make my private field _x public or define a public x getter.
This PR addresses what you want:
https://github.com/google/json_serializable.dart/pull/1256/files#diff-0acaf4c472e452d1e5d215a15fcd2266ccd02ab6abdfac0080c2fca845eb9096
You will be able to explicitly set includeFromJson and includeToJson on the private fields you want to include.
Example:
class X {
#JsonKey(includeFromJson: true, includeToJson: true)
int _includeMeToTheJsonParsing;
}
It was merged November 30th. Latest package version is v6.5.4, released at October 25th. So you will need to wait a little bit if you want the official release. Otherwise, you can point directly to the latest commit if you need it ASAP.
If you don't want to make your private field public or define a public getter, you can still use a serialization library like json_serializable or built_value to serialize and deserialize the class, but you will need to define a custom toJson method that manually serializes the private field. Here's an example of using json_serializable with a custom toJson method:
import 'package:json_annotation/json_annotation.dart';
part 'my_class.g.dart';
#JsonSerializable()
class MyClass {
final int _x;
MyClass(this._x);
Map<String, dynamic> toJson() => {
'x': _x,
};
factory MyClass.fromJson(Map<String, dynamic> json) => MyClass(json['x'] as int);
}
You can then use the fromJson and toJson methods to serialize and deserialize your class:
import 'dart:convert';
void main() {
// Serialize to JSON
MyClass obj = MyClass(42);
String json = jsonEncode(obj);
// Deserialize from JSON
MyClass obj2 = MyClass.fromJson(jsonDecode(json));
}

How to deserialize Date ISO String to DateTime Object in built_value serialization in dart?

I wanna serialize a json object including an ISOString date to a dart object using built value.
this is a sample json:
{
"title": "test",
"description": "test description",
"date": "2020-06-05T11:42:38.585Z",
"creator": {
"email": "test#test.com"
}
}
this is the model:
abstract class Post implements Built<Post, PostBuilder> {
#nullable
#BuiltValueField(wireName: '_id')
String get id;
String get title;
String get description;
DateTime get date;
#nullable
User get creator;
Post._();
static Serializer<Post> get serializer => _$postSerializer;
factory Post([updates(PostBuilder b)]) = _$Post;
factory Post.fromJson(Map<String, dynamic> map) =>
serializers.deserializeWith(Post.serializer, map);
Map<String, dynamic> toJson() =>
serializers.serializeWith(Post.serializer, this);
}
and this is the error:
Deserializing '[title, test1, description, test1 description, date, 2020-06-05T...' to
'Post' failed due to: Deserializing '2020-06-05T11:42:38.585Z' to 'DateTime' failed due
to: type 'String' is not a subtype of type 'int' in type cast
how do I fix that?
You can import the Iso8601DateTimeSerializer directly from built_value - don't copy the file over to your project.
Your final serializers.dart should look like:
import 'package:built_value/iso_8601_date_time_serializer.dart';
import 'package:built_value/iso_8601_duration_serializer.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
part 'serializers.g.dart';
#SerializersFor([
// your built value classes
])
final Serializers serializers = (_$serializers.toBuilder()
..add(Iso8601DateTimeSerializer())
..add(Iso8601DurationSerializer())
..addPlugin(StandardJsonPlugin())
).build();
You need to add a custom DateTime serializer that you can find here: Iso8601DateTimeSerializer
create a new dart file (I named it iso8601_date_time_serializer.dart)
paste the code from 1
add the import to your serializers.dart file (import 'iso8601_date_time_serializer.dart';)
edit your serializers.g.dart file
Serializers _$serializers = (new Serializers().toBuilder()
..add(Iso8601DateTimeSerializer())
..add(Post.serializer) // I assume you have this in yours
..addPlugin(StandardJsonPlugin()))
.build();
Please note that this modification might be deleted if you regenerate the code with build_runner.
In case you want to dig deeper, I got the answer from built_value GitHub issue 454

How to send with 'params.put' in Dart or Flutter JsonObjectLite

In java it would be something like this ...
public Request compose(LoginDevice login) {
JSONObject params = new JSONObject();
try {
if (login.granType != null)
params.put("grant_type", login.granType);
if (login.clientId != null)
params.put("client_id", login.clientId);
} catch (JSONException e) {
e.printStackTrace();
}
return (Request)new BaseRequest("oauth/v2/token", params.toString(), new HashSet());
}
And in Dart and tried something similar but it doesn't work... the parameter 'put' does not exist in JsonObjectLite...
Request compose(LoginDevice login)
{
JsonObjectLite params = new JsonObjectLite();
try {
if (login.granType != null) {
params.put("grant_type", login.granType);
}
if (login.clientId != null) {
params.put("client_id", login.clientId);
}
} on JsonObjectLiteException catch (e) {
print(e);
}
return new BaseRequest("oauth/v2/token", params.toString(), new HashSet());
}
How could I do it? Thank you
The class JsonObjectLite doesn't contain the method put.
How you can understand dart doesn't is Java, in this cases your the class JsonObjectLite has a method called putIfAbsent, the implementation is the following
/// If [isImmutable] is false, or the key already exists,
/// then allow the edit.
/// Throw [JsonObjectLiteException] if we're not allowed to add a new
/// key
#override
void putIfAbsent(dynamic key, Function() ifAbsent) {
if (isImmutable == false || containsKey(key)) {
_objectData.putIfAbsent(key, ifAbsent);
} else {
throw const JsonObjectLiteException('JsonObject is not extendable');
}
}
look also the Source code
So an example of code should be the following
import 'package:json_object_lite/json_object_lite.dart';
class AuthorAnswer {
var _username;
var _status;
AuthorAnswer(this._username, this._status);
String get username => _username;
String get status => _status;
}
int main() {
var author = '#vincenzopalazzo';
var sentences = 'Follow me on Github';
var authorObject = AuthorAnswer(author, sentences);
try{
JsonObjectLite params = new JsonObjectLite();
params.isImmutable = false;
params.putIfAbsent("author", () => authorObject.username);
params.putIfAbsent("sencence", () => authorObject.status);
print(params.toString());
} on JsonObjectLiteException catch (err){
print('--------- ERROR ----------');
print(err);
}
return 0;
}
You should be set the params.isImmutable = false and after you can add your propriety, with your logic.
In my opinion, I don't see any motivation to use this library, dart have 2 types of the module to implement the serialization, and I think should better use it because on the web exist the documentation, like this dart json, flutter json
Inside the flutter app, there are also the line guides, for the small application you can use dart:convert:json also for the other you can use the json_serializable
I want to add also an example of dart:convert
/**
*
*/
import "dart:core";
import "dart:convert";
class ClassToJsonOne {
var _propOne;
var _propTwo;
ClassToJsonOne(this._propOne, this._propTwo);
Map<String, dynamic> toJSon() => {
'prop_one': _propOne,
'prop_two': _propTwo
};
ClassToJsonOne.fromJson(Map<String, dynamic> json):
_propOne = json['prop_one'],
_propTwo = json['prop_two'];
#override
String toString() => 'First Class: $_propOne, $_propTwo';
}
class ClassToJsonTwo{
var _propOne;
var _propTwo;
ClassToJsonTwo(this._propOne, this._propTwo);
Map<String, dynamic> toJSon() => {
'prop_one': _propOne,
'prop_two': _propTwo
};
ClassToJsonTwo.fromJson(Map<String, dynamic> json):
_propOne = json['prop_one'],
_propTwo = json['prop_two'];
#override
String toString() => 'Second Class: $_propOne, $_propTwo';
}
main(List<String> args) {
print('------- Declare Objecr -------\n');
var objectToJsonOne = ClassToJsonOne('I am the fist object', 'empty');
var objectToJsonTwo = ClassToJsonTwo('I contains the first object', 'empty');
String jsonStringObjOne = jsonEncode(objectToJsonOne.toJSon());
print('\n---------- Object one JSON format ---------\n');
print(jsonStringObjOne);
String jsonStringObjTwo = jsonEncode(objectToJsonTwo.toJSon());
print('\n---------- Object one JSON format ---------\n');
print(jsonStringObjTwo);
print('\n---------- DECODE JSON to OBJECT ---------\n');
var fromJsonObjectOne = jsonDecode(jsonStringObjOne);
print(fromJsonObjectOne.toString());
var fromJsonObjectTwo = jsonDecode(jsonStringObjTwo);
print(fromJsonObjectTwo.toString());
}
Inside the classes, you can see the following methods
Map<String, dynamic> toJSon() => {
'prop_one': _propOne,
'prop_two': _propTwo
};
ClassToJsonTwo.fromJson(Map<String, dynamic> json):
_propOne = json['prop_one'],
_propTwo = json['prop_two'];
The result of the method toJSon, you should be pass to the method of the library jsonEncode and when you go to deserialize you can use the library method jsonDecode(youtStringJSOn) and the result you can pass to the method of your class fromJson.
In addition, you can configure the library json_serializable.
In conclusion, I want to fix my comment
I think the json_serializable worked how GSON, I can make an example for you, on this day.
On flutter, documentation has reported this text
Is there a GSON/Jackson/Moshi equivalent in Flutter?
The simple answer is no.
Such a library would require using runtime reflection, which is disabled in Flutter. Runtime reflection interferes with tree shaking, which Dart has supported for quite a long time. With tree shaking, you can “shake off” unused code from your release builds. This optimizes the app’s size significantly.
Since reflection makes all code implicitly used by default, it makes tree shaking difficult. The tools cannot know what parts are unused at runtime, so the redundant code is hard to strip away. App sizes cannot be easily optimized when using reflection.
Although you cannot use runtime reflection with Flutter, some libraries give you similarly easy-to-use APIs but are based on code generation instead. This approach is covered in more detail in the code generation libraries section.
you can found the source code inside this answer here

Flutter: Shuffle BuiltList in Package built_value

I've developed an app that receives questions from an API.
The client uses built_value for checking.
Is there a way to shuffle the objects in
BuiltList<Aufgabe>fragen ?
This is what the client should do.
abstract class Aufgabenbundle
implements Built<Aufgabenbundle, AufgabenbundleBuilder> {
String get nameDerUebung;
String get dateiNameDerPdf;
BuiltList<Aufgabe> get fragen; //These objects should be mixed
Aufgabenbundle._();
factory Aufgabenbundle([updates(AufgabenbundleBuilder b)]) = _$Aufgabenbundle;
String toJson() {
return json
.encode(serializers.serializeWith(Aufgabenbundle.serializer, this));
}
static Aufgabenbundle fromJson(String jsonString) {
return serializers.deserializeWith(
Aufgabenbundle.serializer, json.decode(jsonString));
}
static Serializer<Aufgabenbundle> get serializer => _$aufgabenbundleSerializer;
}
abstract class Aufgabe
implements Built<Aufgabe, AufgabeBuilder> {
String get title;
String get frage;
int get schwierigkeit;
int get antwortZeit;
BuiltList<String> get vorgegebeneAntworten;
int get richtigeAntwort;
#nullable
int get angehakteWert;
Aufgabe._();
factory Aufgabe([updates(AufgabeBuilder b)]) = _$Aufgabe;
static Serializer<Aufgabe> get serializer => _$aufgabeSerializer;
}
The BuiltList is immutable, so you can't shuffle it directly. As with other mutating operations, you need to rebuild it instead.
When you do that, you get a ListBuilder which implements the List interface, including the shuffle method.
So:
var fragen = aufgabenbundle.fragen;
var gemischteFragen = fragen.rebuild((b) => b.shuffle());