Home > Back-end >  Flutter - How to write String into json files
Flutter - How to write String into json files

Time:01-22

I followed the guide in the flutter doc and didnt understand how it works.

I have a existing file containing users info, and I want to be able to write/update the file.

Here's the relevant parts of my code:

Future<bool> sendMessage(String sender, String target, String body) async {
    String tempAccountData = await loadMessage();
    List<Map<String, dynamic>> accountData =
        List<Map<String, dynamic>>.from(jsonDecode(tempAccountData));
    //find valid target
    print(accountData);
    print(target);
    for (Map<String, dynamic> accountInfo in accountData) {
      if (accountInfo["username"] == target) {
        //write message
        accountInfo["messages"]
            .add({"time": DateTime.now(), "sender": sender, "message": body});
        writeMessage(accountData);
        return true;
      }
    }
    return false;
  }

  Future<String> get _localPath async {
    final directory = await getApplicationDocumentsDirectory();

    return directory.path;
  }

  Future<File> get _localFile async {
    final path = await _localPath;
    print(path);
    return File('$path/accountInfo.json');
  }

  Future<File> writeMessage(List<Map<String, dynamic>> accountData) async {
    File file = await _localFile;

    // Write the file
    return file.writeAsString('$accountData');
  }

I didnt know what the path is, and I put the file into assets/data as seen in the screenshot below: (I'm trying to read/write accountInfo.json from accountInfo.dart) Directory of accountInfo.json and accountInfo.dart

CodePudding user response:

It's not possible to modify a file in the assets during runtime.

What you can do is write all the data in the Json to a file in one of the device's directories and then modify that file when needed or use a database to store all the data.

CodePudding user response:

There are a few steps that need to happen and things you'll need to know. First of all, assets are immutable. This means you can read from them, but you're not able to write to them. What you'll need is a local file. A file that lives on the file system of the device where the app is installed. This file can be modified, and will allow writing to it.

The process would go as follows:

  1. Check if there's already a local file
  2. If not, create it and put the contents of an initial asset file onto it.
  3. Now that the mutable local file exists, read and write from it.

Here's a code sample of a class that takes care of that:

import 'dart:io';

import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';

const initialAssetFile = 'assets/initial.json';
const localFilename = 'data.json';

class Repository {
  /// Initially check if there is already a local file.
  /// If not, create one with the contents of the initial json in assets
  Future<File> _initializeFile() async {
    final localDirectory = await getApplicationDocumentsDirectory();
    final file = File('$localDirectory/$localFilename');

    if (!await file.exists()) {
      // read the file from assets first and create the local file with its contents
      final initialContent = await rootBundle.loadString(initialAssetFile);
      await file.create();
      await file.writeAsString(initialContent);
    }

    return file;
  }

  Future<String> readFile() async {
    final file = await _initializeFile();
    return await file.readAsString();
  }

  Future<void> writeToFile(String data) async {
    final file = await _initializeFile();
    await file.writeAsString(data);
  }
}

It will basically check before every read or write if the local file has already been created, and will take care of that if not.

Note that there's no JSON specific things happening here, this is just default file IO. JSON encoding/decoding should happen before/after this.

You'll just need to add an initial file into the assets/ folder and specify that in your pubspec.yaml as follows:

flutter:
  assets:
    - assets/initial.json # the file containing the initial data
#   - assets/ # you can also just add the whole directory

Once that's done, you should be able to use readFile() and writeFile(String data) from this Repository class.

(It might be important to make sure WidgetsFlutterBinding.ensureInitialized(); has been called in order to interact with the local file system)

  •  Tags:  
  • Related