[{"data":1,"prerenderedAt":22},["ShallowReactive",2],{"articolo-serializzazione-json-in-flutter-con-json-serializable-e-build-runner":3,"comments-article-serializzazione-json-in-flutter-con-json-serializable-e-build-runner":21},{"id":4,"title":5,"slug":6,"excerpt":7,"body":8,"cover_image":9,"video_url":10,"status":11,"published_at":12,"meta_title":13,"meta_description":14,"category":15,"author":19},33,"Serializzazione JSON in Flutter con json_serializable e build_runner","serializzazione-json-in-flutter-con-json-serializable-e-build-runner","Gestire il parsing di JSON manualmente diventa presto ingestibile. Scopri come automatizzare la serializzazione in Flutter con json_serializable, freezed e build_runner per un codice più sicuro e manutenibile.","## Perché automatizzare la serializzazione JSON\n\nQuasi tutte le app Flutter comunicano con API REST che restituiscono dati in formato JSON. Scrivere manualmente i metodi `fromJson` e `toJson` per ogni modello è noioso, ripetitivo e soprattutto soggetto a errori: basta un nome di campo sbagliato per introdurre bug difficili da individuare.\n\nLa libreria `json_serializable`, insieme a `build_runner`, permette di **generare automaticamente** il codice di serializzazione a partire dalle annotazioni sulle nostre classi. Il risultato è un codice type-safe, verificato in fase di compilazione e sempre coerente con la definizione del modello.\n\n## Configurazione delle dipendenze\n\nAggiungiamo le dipendenze necessarie nel `pubspec.yaml`:\n\n```yaml\ndependencies:\n  json_annotation: ^4.9.0\n\ndev_dependencies:\n  build_runner: ^2.4.13\n  json_serializable: ^6.8.0\n```\n\n`json_annotation` contiene le annotazioni, mentre `json_serializable` e `build_runner` sono strumenti di sviluppo usati solo in fase di generazione del codice.\n\n## Creare un modello serializzabile\n\nDefiniamo una classe `User` annotata con `@JsonSerializable()`:\n\n```dart\nimport 'package:json_annotation\u002Fjson_annotation.dart';\n\npart 'user.g.dart';\n\n@JsonSerializable()\nclass User {\n  final int id;\n  final String name;\n  final String email;\n\n  User({\n    required this.id,\n    required this.name,\n    required this.email,\n  });\n\n  factory User.fromJson(Map\u003CString, dynamic> json) => _$UserFromJson(json);\n\n  Map\u003CString, dynamic> toJson() => _$UserToJson(this);\n}\n```\n\nLa direttiva `part 'user.g.dart';` collega il file generato. Le funzioni `_$UserFromJson` e `_$UserToJson` non esistono ancora: verranno create dal generatore.\n\n## Generare il codice\n\nEseguiamo il comando:\n\n```bash\ndart run build_runner build --delete-conflicting-outputs\n```\n\nDurante lo sviluppo è comodo usare la modalità watch, che rigenera i file automaticamente a ogni modifica:\n\n```bash\ndart run build_runner watch --delete-conflicting-outputs\n```\n\nVerrà creato il file `user.g.dart` con l'implementazione dei metodi.\n\n## Gestire nomi di campo diversi\n\nSpesso le API usano lo `snake_case` mentre in Dart preferiamo il `camelCase`. Possiamo mappare i campi con `@JsonKey`:\n\n```dart\n@JsonSerializable()\nclass User {\n  final int id;\n  final String name;\n\n  @JsonKey(name: 'created_at')\n  final DateTime createdAt;\n\n  @JsonKey(defaultValue: false)\n  final bool isActive;\n\n  User({\n    required this.id,\n    required this.name,\n    required this.createdAt,\n    required this.isActive,\n  });\n\n  factory User.fromJson(Map\u003CString, dynamic> json) => _$UserFromJson(json);\n  Map\u003CString, dynamic> toJson() => _$UserToJson(this);\n}\n```\n\nIn alternativa, per evitare di annotare ogni singolo campo, possiamo configurare la conversione globale:\n\n```dart\n@JsonSerializable(fieldRename: FieldRename.snake)\nclass User {\n  \u002F\u002F i campi camelCase verranno mappati in snake_case automaticamente\n}\n```\n\n## Oggetti annidati e liste\n\n`json_serializable` gestisce automaticamente oggetti annidati, a patto che anche loro siano serializzabili:\n\n```dart\n@JsonSerializable()\nclass Post {\n  final int id;\n  final String title;\n  final User author;\n  final List\u003CString> tags;\n\n  Post({\n    required this.id,\n    required this.title,\n    required this.author,\n    required this.tags,\n  });\n\n  factory Post.fromJson(Map\u003CString, dynamic> json) => _$PostFromJson(json);\n  Map\u003CString, dynamic> toJson() => _$PostToJson(this);\n}\n```\n\nIl generatore chiamerà `User.fromJson` per il campo `author` e convertirà la lista di tag senza codice aggiuntivo.\n\n## Conversioni personalizzate con JsonConverter\n\nQuando dobbiamo trasformare un valore in modo non standard (per esempio un timestamp Unix in `DateTime`), usiamo un `JsonConverter`:\n\n```dart\nclass TimestampConverter implements JsonConverter\u003CDateTime, int> {\n  const TimestampConverter();\n\n  @override\n  DateTime fromJson(int json) =>\n      DateTime.fromMillisecondsSinceEpoch(json * 1000);\n\n  @override\n  int toJson(DateTime object) => object.millisecondsSinceEpoch ~\u002F 1000;\n}\n```\n\nSi applica così al campo:\n\n```dart\n@TimestampConverter()\nfinal DateTime createdAt;\n```\n\n## Integrazione con freezed\n\nPer modelli immutabili con `copyWith`, uguaglianza e supporto alle union, la combinazione con `freezed` è la scelta più diffusa:\n\n```dart\nimport 'package:freezed_annotation\u002Ffreezed_annotation.dart';\n\npart 'user.freezed.dart';\npart 'user.g.dart';\n\n@freezed\nclass User with _$User {\n  const factory User({\n    required int id,\n    required String name,\n    @JsonKey(name: 'created_at') required DateTime createdAt,\n  }) = _User;\n\n  factory User.fromJson(Map\u003CString, dynamic> json) => _$UserFromJson(json);\n}\n```\n\nCon `freezed` non dobbiamo nemmeno scrivere `toJson`: viene generato insieme a `copyWith`, `toString` e `==`.\n\n## Best practice\n\n- **Non modificare mai i file `.g.dart`**: vengono rigenerati e le modifiche andrebbero perse.\n- Aggiungi i file generati al controllo di versione oppure escludili con `.gitignore` rigenerandoli in CI, in base alla strategia del team.\n- Usa `--delete-conflicting-outputs` per evitare errori quando cambi la struttura dei modelli.\n- Centralizza le configurazioni comuni in un file `build.yaml` per applicarle a tutti i modelli.\n\n## Conclusione\n\nL'uso di `json_serializable` e `build_runner` elimina il codice ripetitivo, riduce gli errori e mantiene i modelli sempre allineati con i dati ricevuti dalle API. Abbinandolo a `freezed` ottieni modelli immutabili robusti con pochissimo sforzo, portando la gestione del JSON a un livello professionale.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Farticles\u002F962319bc-4829-41b8-9cb1-9c883bccddaf.jpg",null,"published","2026-07-07T04:00:37+00:00","Serializzazione JSON in Flutter con json_serializable","Guida pratica alla serializzazione JSON in Flutter: automatizza fromJson e toJson con json_serializable, build_runner e freezed per codice type-safe.",{"id":16,"name":17,"slug":18},1,"Guide","guide",{"id":16,"name":20},"Flutter Bot",[],1785219603107]