DEV Community

loading...
Cover image for Conversão automática de Json usando json_serializable #1

Conversão automática de Json usando json_serializable #1

Pedro Massango
Software Engineer at Monstarlab
・3 min read

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);
}
Enter fullscreen mode Exit fullscreen mode

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(),
    };
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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.

  1. Setando a propiedade explicitToJson para true, o pacote vai então chamar fromJson/toJson sempre que precisar converter um tipo de dado desconhecido, neste caso quando ela precisar converter a propiedade location.
@JsonSerializable(explicitToJson: true)
class User {
  ...
}
Enter fullscreen mode Exit fullscreen mode
  1. 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);
}
Enter fullscreen mode Exit fullscreen mode

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.

Discussion (0)