Pedro Massango
Posted on February 21, 2020
Depois de muito tempo, estou de volta na publicação de artigos, neste artigo vamos vou mostrar prar vocês como simplicar aquela tarefa chata que ninguém quer fazer, a redução de boilerplate quando estamos trabalhando com conversão de de uma classe Dart para json e vice-versa.
Todo desenvolvedor Flutter já se deparou com o problema de escrever as funções fromJson
e toJson
quanto estamos trabalhando com base de dados ou mesmo consumindo recursos de algum servidor. É um trabalho simples para projetos bem pequenos, mas quando vamos trabalhar com projetos grande chega a ser uma tarefa difícil de gerir a longo prazo.
Por este motivo websites como o Quicktype (um conversor de Json para classes de diferentes linguagens, incluindo Dart) se tornaram famosos e são ferramentas que estão sendo cada vez mais usadas no dia-a-dia dos desenvolvedores.
Eu vou mostrar para você um jeito mais simples de fazer isso usando um pacote Dart que gera as funções fromJson
e toJson
para você.
json_serializable
É um pacote da linguagem Dart que simplifica a conversão de uma classe Dart para json e vice-versa através da geração de código, continue lendo para ver o funcionamento dela.
Do contrário ao Quicktype este pacote evita ter classes conversoras de de objectos, já que todo trabalho sujo é transparente para o desenvolvedor em um arquivo separado.
Vamos dizer que temos a seguinte classe User
em nosso projeto, e precisamos fazer com ele suporte conversão automática para json, tudo o que precisamos fazer é:
- [x] Adicionar
part 'user.g.dart';
(user, é o nome do ficheiro onde se encontra a classe) - [x] Anotar a classe com a anotação
@JsonSerializable()
- [x] Configurar a classe para usar as funcões gerada pelo pacote.
Com todos os passos feitos, teremos uma classe parecida com:
part of 'user.dart';
@JsonSerializable()
class User {
final String firstName;
final String lastName;
final DateTime dateOfBirth;
User({this.firstName, this.lastName, this.dateOfBirth});
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
De momento a IDE poderá mostrar erros nas últimas linhas da classe, isso porque não geramos o codigo necessário para o funcionamento da classe. Após a execução de flutter pub run build_runner build
teremos o problema resolvido e vai aparecer um novo ficheiro user.g.dart
com o seguinte:
part of 'user.dart';
User_$UserFromJson(Map<String, dynamic> json) {
return User(
firstName: json['firstName'] as String,
lastName: json['lastName'] as String,
dateOfBirth: DateTime.parse(json['dateOfBirth'] as String),
);
}
Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{
'firstName': instance.firstName,
'lastName': instance.lastName,
'dateOfBirth': instance.dateOfBirth.toIso8601String(),
};
Este é o arquivo que contém o código gerado, o codigo necessário para a conversão automática da sua classe para json. Não se preocupe, você não precisa saber da existência deste arquivo, e nem precisa usar ele.
Conversão de Classes usando outras classes como propiedades.
Por padrão este pacote não suporta conversão de propriedades de tipos desconhecidos, o que pode causar problema se você tiver uma classe do tipo:
@JsonSerializable()
class User {
final Location location;
User({this.location});
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
O que o pacote vai fazer é tentar converter a instância de location
para string, e uma vez que ela não é string irá disparar uma esceção de conversão.
Para resolver este problema, nós devemos fazer duas coisas: dizer ao pacote para que chame a função fromJson
/toJson
em objectos desconhecidos, e adicionar tais funções em nossos objectos.
- Setando a propiedade
explicitToJson
paratrue
, o pacote vai então chamarfromJson
/toJson
sempre que precisar converter um tipo de dado desconhecido, neste caso quando ela precisar converter a propiedadelocation
.
@JsonSerializable(explicitToJson: true)
class User {
...
}
- Definir
fromJson
/toJson
na classe que precisa de conversão.
part of 'location.dart';
@JsonSerializable()
class Location {
final double lat;
final double lgn;
User({this.lat, this.lng});
factory Location.fromJson(Map<String, dynamic> json) => _$LocationFromJson(json);
Map<String, dynamic> toJson() => _$LocationToJson(this);
}
E com isso a conversão automática agora funciona com objectos de tipos desconhecidos, ou seja com classes criadas por nós.
OBS: o pacote pode ser encontrado aqui.
Por hoje é tudo, segue para a parte dois, onde veremos conceitos mais avançados deste pacote.
Posted on February 21, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.