[{"data":1,"prerenderedAt":75},["ShallowReactive",2],{"tutorial-salvare-e-leggere-file-json-nel-dispositivo-con-flutter-e-path-provider":3,"comments-tutorial-salvare-e-leggere-file-json-nel-dispositivo-con-flutter-e-path-provider":74},{"id":4,"title":5,"slug":6,"excerpt":7,"intro":8,"cover_image":9,"video_url":10,"difficulty":11,"estimated_minutes":12,"flutter_version":13,"status":14,"published_at":15,"meta_title":16,"meta_description":17,"category":18,"author":22,"steps":24},51,"Salvare e leggere file JSON nel dispositivo con Flutter e path_provider","salvare-e-leggere-file-json-nel-dispositivo-con-flutter-e-path-provider","Impara a leggere e scrivere file JSON persistenti nella memoria dell'app usando path_provider e dart:io, con una classe di storage riutilizzabile.","In molte app hai bisogno di salvare dati strutturati che sopravvivano alla chiusura dell'app, ma senza la complessità di un database. In questo tutorial vedremo come serializzare oggetti Dart in file JSON e salvarli nella directory dei documenti dell'applicazione usando `path_provider` e `dart:io`.\n\nRealizzeremo una piccola app di gestione note che salva una lista di oggetti su disco e la ricarica all'avvio. Imparerai a:\n\n- ottenere il percorso corretto per i file dell'app\n- serializzare e deserializzare oggetti in JSON\n- creare una classe di storage riutilizzabile\n- gestire il caso di file inesistente\n\nÈ un pattern leggero, perfetto per configurazioni, cache di dati e piccole collezioni.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Ftutorials\u002F9ae1328a-d4e3-4db7-9773-ab7a1cad6c8f.jpg",null,"intermediate",30,"3.x","published","2026-07-28T04:30:41+00:00","File JSON in Flutter con path_provider: leggere e scrivere","Guida pratica per salvare e leggere file JSON persistenti in Flutter usando path_provider e dart:io con una classe di storage riutilizzabile.",{"id":19,"name":20,"slug":21},1,"Guide","guide",{"id":19,"name":23},"Flutter Bot",[25,32,40,47,54,61,68],{"id":26,"position":19,"title":27,"body":28,"code_snippet":29,"code_language":30,"expected_result":31,"demo_url":10,"video_url":10},343,"Aggiungere la dipendenza path_provider","Il pacchetto `path_provider` fornisce metodi cross-platform per ottenere i percorsi delle directory di sistema (documenti, cache, temp). Aggiungilo al progetto.\n\nEsegui il comando da terminale oppure aggiungilo manualmente al `pubspec.yaml`.","flutter pub add path_provider","bash","Nel pubspec.yaml compare la dipendenza path_provider e `flutter pub get` viene eseguito con successo.",{"id":33,"position":34,"title":35,"body":36,"code_snippet":37,"code_language":38,"expected_result":39,"demo_url":10,"video_url":10},344,2,"Creare il modello dati serializzabile","Definiamo il modello `Note` con i metodi `toJson` e `fromJson` per convertire l'oggetto da e verso una `Map`. Questa struttura è essenziale per la serializzazione JSON.","class Note {\n  final String id;\n  final String title;\n  final String content;\n\n  Note({required this.id, required this.title, required this.content});\n\n  Map\u003CString, dynamic> toJson() => {\n        'id': id,\n        'title': title,\n        'content': content,\n      };\n\n  factory Note.fromJson(Map\u003CString, dynamic> json) => Note(\n        id: json['id'] as String,\n        title: json['title'] as String,\n        content: json['content'] as String,\n      );\n}","dart","Hai una classe Note in grado di convertirsi in Map e di essere ricostruita da una Map.",{"id":41,"position":42,"title":43,"body":44,"code_snippet":45,"code_language":38,"expected_result":46,"demo_url":10,"video_url":10},345,3,"Ottenere il percorso del file","Usiamo `getApplicationDocumentsDirectory()` di path_provider per ottenere la directory in cui salvare i dati persistenti dell'app. Costruiamo poi un riferimento al file `notes.json`.\n\nQuesta directory è privata all'app e non viene cancellata dal sistema, a differenza della cache.","import 'dart:io';\nimport 'package:path_provider\u002Fpath_provider.dart';\n\nclass NotesStorage {\n  Future\u003CFile> _getFile() async {\n    final dir = await getApplicationDocumentsDirectory();\n    return File('${dir.path}\u002Fnotes.json');\n  }\n}","Il metodo _getFile restituisce un riferimento al file notes.json nella directory dei documenti.",{"id":48,"position":49,"title":50,"body":51,"code_snippet":52,"code_language":38,"expected_result":53,"demo_url":10,"video_url":10},346,4,"Scrivere la lista di note su file","Serializziamo la lista di `Note` in una stringa JSON con `jsonEncode` e la scriviamo sul file con `writeAsString`. Il metodo crea o sovrascrive il file esistente.","import 'dart:convert';\n\nFuture\u003Cvoid> saveNotes(List\u003CNote> notes) async {\n  final file = await _getFile();\n  final jsonList = notes.map((n) => n.toJson()).toList();\n  await file.writeAsString(jsonEncode(jsonList));\n}","Chiamando saveNotes, la lista viene scritta come array JSON nel file notes.json.",{"id":55,"position":56,"title":57,"body":58,"code_snippet":59,"code_language":38,"expected_result":60,"demo_url":10,"video_url":10},347,5,"Leggere le note dal file","Alla lettura dobbiamo gestire il caso in cui il file non esista ancora (primo avvio): in quel caso restituiamo una lista vuota. Altrimenti decodifichiamo il contenuto con `jsonDecode` e ricostruiamo gli oggetti.","Future\u003CList\u003CNote>> loadNotes() async {\n  try {\n    final file = await _getFile();\n    if (!await file.exists()) return [];\n\n    final content = await file.readAsString();\n    if (content.trim().isEmpty) return [];\n\n    final List\u003Cdynamic> jsonList = jsonDecode(content);\n    return jsonList\n        .map((e) => Note.fromJson(e as Map\u003CString, dynamic>))\n        .toList();\n  } catch (e) {\n    \u002F\u002F In caso di file corrotto ripartiamo da lista vuota\n    return [];\n  }\n}","loadNotes restituisce la lista salvata, oppure una lista vuota se il file non esiste o è corrotto.",{"id":62,"position":63,"title":64,"body":65,"code_snippet":66,"code_language":38,"expected_result":67,"demo_url":10,"video_url":10},348,6,"Usare lo storage in un widget","Integriamo la classe in una schermata: carichiamo le note all'avvio con `initState` e le aggiorniamo salvandole quando aggiungiamo un elemento. Usiamo un `FutureBuilder` o uno stato locale per mostrarle.","class NotesScreen extends StatefulWidget {\n  const NotesScreen({super.key});\n  @override\n  State\u003CNotesScreen> createState() => _NotesScreenState();\n}\n\nclass _NotesScreenState extends State\u003CNotesScreen> {\n  final _storage = NotesStorage();\n  List\u003CNote> _notes = [];\n\n  @override\n  void initState() {\n    super.initState();\n    _load();\n  }\n\n  Future\u003Cvoid> _load() async {\n    final notes = await _storage.loadNotes();\n    setState(() => _notes = notes);\n  }\n\n  Future\u003Cvoid> _addNote() async {\n    final note = Note(\n      id: DateTime.now().millisecondsSinceEpoch.toString(),\n      title: 'Nuova nota',\n      content: 'Contenuto di esempio',\n    );\n    setState(() => _notes.add(note));\n    await _storage.saveNotes(_notes);\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: const Text('Note')), \n      floatingActionButton: FloatingActionButton(\n        onPressed: _addNote,\n        child: const Icon(Icons.add),\n      ),\n      body: ListView.builder(\n        itemCount: _notes.length,\n        itemBuilder: (context, i) => ListTile(\n          title: Text(_notes[i].title),\n          subtitle: Text(_notes[i].content),\n        ),\n      ),\n    );\n  }\n}","L'app mostra la lista di note, ne aggiunge di nuove al tap sul FAB e le ricarica correttamente dopo il riavvio.",{"id":69,"position":70,"title":71,"body":72,"code_snippet":10,"code_language":38,"expected_result":73,"demo_url":10,"video_url":10},349,7,"Testare la persistenza","Per verificare che tutto funzioni: avvia l'app, aggiungi alcune note, chiudi completamente l'applicazione (non solo in background) e riaprila.\n\n**Suggerimento:** su Android puoi ispezionare il file salvato tramite Android Studio > Device File Explorer nel percorso `data\u002Fdata\u002F\u003Cpackage>\u002Fapp_flutter\u002Fnotes.json`. Ricordati che questo approccio è ideale per collezioni piccole; per grandi volumi o query complesse preferisci un database come SQLite.","Dopo la riapertura dell'app le note aggiunte in precedenza sono ancora presenti, confermando la persistenza su file JSON.",[],1785219595209]