Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugin: Object to JSON mapper #9318

Closed
dbacinski opened this issue Apr 10, 2017 · 13 comments
Closed

Plugin: Object to JSON mapper #9318

dbacinski opened this issue Apr 10, 2017 · 13 comments

Comments

@dbacinski
Copy link
Contributor

dbacinski commented Apr 10, 2017

It would be nice to have Flutter support for mapping objects to JSON and JSON to object.

Currently to achieve that I have to transcode object to Map. There is no clean way to do that because Flutter do not support dart:mirrors. Only way to do that without code written by hand is to use https://github.com/google/built_value.dart but it is still far from perfect and it needs additional setup.

When I have a Map then I can use JSON.encode to produce JSON string.

This is a code that I am currently using:

class AuthToken {
  final String accessToken;
  final String tokenType;
  final int expiresIn;
  final String refreshToken;
  final int createdAt;

  AuthToken.fromMap(Map<String, dynamic> map)
      :
        accessToken = map["access_token"],
        tokenType = map["token_type"],
        expiresIn = map["expires_in"],
        refreshToken = map["refresh_token"],
        createdAt = map["created_at"];

  Map <String, dynamic> toMap() {
    return {
      "access_token": accessToken,
      "token_type": tokenType,
      "expires_in": expiresIn,
      "refresh_token": refreshToken,
      "created_at": createdAt,
    };
  }
}
  Future save(AuthToken token) async {
    var tokenMap = token.toMap();
    var tokenJson = JSON.encode(tokenMap);
    await _db.put(tokenJson, "auth");
  }

  Future<AuthToken> getToken() async {
    var tokenJson = await _db.get("auth");
    var tokenMap = JSON.decode(tokenJson);
    return new AuthToken.fromMap(tokenMap);
  }

Would be nice to be able to call JSON.encode directly on object and get JSON string, and convert back JSON string to object using JSON.decode. Or at least to have similar functions to transcode objects to Maps.

It would help a lot in the use cases:

  • storing objects in the key-value database
  • using HTTP REST apis
@hundeva
Copy link

hundeva commented Apr 11, 2017

Little bit off topic here, but when mentioning storing objects in the key-value database, what database do you have in mind? As far as I know, there is currently no designated solution, but I'm also looking for one.

@eseidelGoogle
Copy link
Contributor

There are several key-value storage related bugs on file, including #4757 and #6676 and #8901

@eseidelGoogle
Copy link
Contributor

See also #9236 which is a documentation request around json handling.

@eseidelGoogle eseidelGoogle added this to the 4: Make shippers happy milestone Apr 11, 2017
@dbacinski
Copy link
Contributor Author

@hundeva I am using https://github.com/tekartik/sembast.dart but this is more like off topic

@eseidelGoogle I saw those tickets but none of them solves the problem. There is no easy way to map object to JSON and back. And this is what other frameworks like React Native provide out of the box.

@zoechi
Copy link
Contributor

zoechi commented Apr 12, 2017

See also https://twitter.com/MatanLurey/status/840355401421930496

@hundeva
Copy link

hundeva commented Apr 12, 2017

@dbacinski Thanks, I decided to use sembast for now as well.

On topic: I think what we would like is something like Gson, for example:

JSON to Object mapping:

Pojo pojo = new Gson().fromJson(jsonString, Pojo.class);

Object to JSON mapping:

String jsonString = new Gson().toJson(pojo);

By default, this wouldn't really work because of no dart:mirrors support. On android, development shifted from using reflection at runtime to using generated code based on annotation processing, in the build step. Is this something that sounds feasible for flutter? I would be perfectly happy, if all I would need to do is, annotate my fields with for example SerializedName('myFieldName'), and then I could call Pojo pojo = JSON.decode(jsonString);

I'm yet to dig in to the build process, so I have no idea how much annotation processing is supported at the moment.

Alternatively, if annotation processing is not supported, I'd be fine with writing (de)serializers where I handle JsonElement objects, and its descendants (JsonObject, JsonArray, JsonPrimitive, JsonNull), instead of handling maps. Again, the example is from Gson.

@zoechi
Copy link
Contributor

zoechi commented Apr 12, 2017

@hundeva this should work fine with a code generator similar to what built_value uses or other packages that use code generation. I'd suggest trying built_value first. I think it's immutability approach is a great fit for Flutter.

@hundeva
Copy link

hundeva commented Apr 12, 2017

Yeah, I've checked out built_value some time ago, my problem with that is, the developer needs to write some non trivial boilerplate by hand, which is fairly error prone, at least I had some trouble with it. :) Also, the code generation has to be invoked manually, and the generated code has to be pushed to the repos as well.

I found it easier to fallback to manually parsing the objects from maps, which is still not the best solution.

@zoechi
Copy link
Contributor

zoechi commented Apr 12, 2017

Also, the code generation has to be invoked manually, and the generated code has to be pushed to the repos as well.

AFAIK think this can't be avoided except by using mirrors
Manual coded (de)serialization also needs to be checked in.

I'd expect code generation to be integrated better into the build process. Not sure how the Flutter team sees this but for normal Dart development (server, web) this the direction they are heading AFAIK.

write some non trivial boilerplate by hand

I think it's rather trivial (just my opinion of course) and can be made even easier by using for example something like live templates of IntelliJ IDEs (most other IDEs have similar features)

@hundeva
Copy link

hundeva commented Apr 12, 2017

Manual coded (de)serialization also needs to be checked in.

Yeah, and this is what I would skip, if possible. Again, I can bring an android example only (as that is what I have worked with for the last 5 years), android-apt does all this for you, and you don't need to check in any generated code.

I'd expect code generation to be integrated better into the build process

That is the direction that I would head, fingers crossed.

I think it's rather trivial (just my opinion of course) and can be made even easier by using for example something like live templates of IntelliJ IDEs (most other IDEs have similar features)

I will surely give it another shot, I'm just exploring flutter in my free time for now.

@iNoles
Copy link

iNoles commented Apr 12, 2017

@hundeva android-apt is deprecated in the latest Android Gradle Plugin because it already provides one.

@yjbanov
Copy link
Contributor

yjbanov commented Apr 24, 2018

I am going to close this. Flutter apps work with a variety of serialization formats, not just JSON, and there are a few packages available already:

If the goal is to add a language-level support, consider filing an issue for the Dart language: https://github.com/dart-lang/sdk/issues.

@yjbanov yjbanov closed this as completed Apr 24, 2018
@github-actions
Copy link

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 17, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants