3

Recently migrating to Flutter null safety feature, I have a lot of Classes that I need to update.

For my models, I use fromJson to deserialize the data from a json object. This forces me to put the late keyword for each field that is non optional.

Is that the right approach?

class ServerSession {
  late String sessionId;
  late String refreshToken;
  late String accessToken;

  ServerSession({required this.sessionId, required this.refreshToken, required this.accessToken});

  ServerSession.fromJson(Map<String, dynamic> json) {
    sessionId = json['session_id'] ?? json['sessionId'];
    refreshToken = json['refresh_token'] ?? json['refreshToken'];
    accessToken = json['access_token'] ?? json['accessToken'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['sessionId'] = this.sessionId;
    data['refreshToken'] = this.refreshToken;
    data['accessToken'] = this.accessToken;
    return data;
  }
}
Scaraux
  • 3,841
  • 4
  • 40
  • 80

1 Answers1

8

No, it is not. You should be using the initializer list for initializing fields of your class. You can read more about the initializer list in the language tour.

class ServerSession {
  String sessionId;
  String refreshToken;
  String accessToken;

  ServerSession({required this.sessionId, required this.refreshToken, required this.accessToken});

  ServerSession.fromJson(Map<String, dynamic> json) :
    sessionId = json['session_id'] ?? json['sessionId'],
    refreshToken = json['refresh_token'] ?? json['refreshToken'],
    accessToken = json['access_token'] ?? json['accessToken'];

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['sessionId'] = this.sessionId;
    data['refreshToken'] = this.refreshToken;
    data['accessToken'] = this.accessToken;
    return data;
  }
}

I personally would use the "normal" constructor for the object and make fromJson a factory constructor, though either method works.

class ServerSession {
  String sessionId;
  String refreshToken;
  String accessToken;

  ServerSession({required this.sessionId, required this.refreshToken, required this.accessToken});

  factory ServerSession.fromJson(Map<String, dynamic> json) {
    return ServerSession(
      sessionId: json['session_id'] ?? json['sessionId'],
      refreshToken: json['refresh_token'] ?? json['refreshToken'],
      accessToken: json['access_token'] ?? json['accessToken']
    );
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['sessionId'] = this.sessionId;
    data['refreshToken'] = this.refreshToken;
    data['accessToken'] = this.accessToken;
    return data;
  }
}

Christopher Moore
  • 15,626
  • 10
  • 42
  • 52
  • Regarding the `toJson()` method my compiler is saying that "Don't access members with `this` unless avoiding shadowing.dart(unnecessary_this)". Does that mean we can safely remove all `this.` in the method? – Heikkisorsa Apr 18 '21 at 08:34
  • 1
    @Heikkisorsa Yes you absolutely can remove them. They're implicit. The OP had them in their `toJson` and I didn't modify that method at all so I left them. – Christopher Moore Apr 18 '21 at 14:48