'Writing and Reading JSON files locally in Flutter Doesn't include Quotes

I am writing an object to a JSON file locally. When I try and read it, I receive this error:

E/flutter ( 7621): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: FormatException: Unexpected character (at character 2)
E/flutter ( 7621): {players: [{id: Nebula, setCount: 0 - 0, characters: {char1: ice_climbers, char2: captain_falcon}, notes: }]}
E/flutter ( 7621):  ^

I understand that the reason I'm getting this error is because that player is not between quotes. i.e. "player". I do not know how to write the object as a JSON with the quotes included.

This code was generated by the JsonSerializableGenerator
PlayerList.toJson:

PlayerList _$PlayerListFromJson(Map<String, dynamic> json) {
  return PlayerList(
    (json['players'] as List)
        ?.map((e) =>
            e == null ? null : Player.fromJson(e as Map<String, dynamic>))
        ?.toList(),
  );
}

Map<String, dynamic> _$PlayerListToJson(PlayerList instance) =>
    <String, dynamic>{
      'players': instance.players?.map((e) => e?.toJson())?.toList(),
    };

This is how I read and write the file:

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

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

Future<File> writePlayerData(PlayerList playerList) async {
  final file = await _localFile;
  return file.writeAsString(playerList.toJson().toString());
}

Future<PlayerList> readPlayerData () async {
  try {
    final file = await _localFile;
    String contents = await file.readAsString();
    final jsonResponse = jsonDecode(contents);
    PlayerList playerList = PlayerList.fromJson(jsonResponse);
    return playerList;
  } catch (e) {
    print(e);
    return getPlayerList(); //just loads a placeholder json in the assets folder;
  }
}

What I want the JSON to be formatted as:

{
  "players": [
    {
      "id": "Filler Character",
      "setCount": "0 - 0",
      "characters": {
        "char1": "",
        "char2": ""
      },
      "notes": "Filler Character"
    }
  ]
}

What the program saves:

{players: [{id: Nebula, setCount: 0 - 0, characters: {char1: ice_climbers, char2: captain_falcon}, notes: }]}

Do I need to manually add the quotes back into the JSON, or is there a different way of saving them?



Solution 1:[1]

Let, test.json is a locally stored json file in your desktop. test.json -

[
  {"name":"Ash","age":"22","hobby":"golf"},
  {"name":"philip","age":"17","hobby":"fishing"},
  {"name":"charles","age":"32","hobby":"drawing"},
]

Now we want to read from it and write to it. The code below does the task. test.dart -

import 'dart:io';
import 'dart:convert';

List<Player> players = [];

void main() async{
    print("hello world");
    final File file = File('D:/Sadi/.../test.json'); //load the json file
    await readPlayerData(file); //read data from json file
    
    Player newPlayer = Player(  //add a new item to data list
      'Samy Brook',
      '31',
      'cooking'
      );

  players.add(newPlayer);

  print(players.length);

  players  //convert list data  to json 
      .map(
        (player) => player.toJson(),
      )
      .toList();
      
    file.writeAsStringSync(json.encode(players));  //write (the whole list) to json file
}

Future<void> readPlayerData (File file) async { 
  
    
    String contents = await file.readAsString();
    var jsonResponse = jsonDecode(contents);
    
    for(var p in jsonResponse){
        
        Player player = Player(p['name'],p['age'],p['hobby']);
        players.add(player);
    }
    
      
}

class Player {
  late String name;
  late String age;
  late String hobby;
  

  Player(
     this.name,
     this.age,
    this.hobby,
  
  );

  Player.fromJson(Map<String, dynamic> json) {
    name = json['name'];
    age = json['age'];
    hobby = json['hobby'];
    
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['name'] = this.name;
    data['age'] = this.age;
    data['hobby'] = this.hobby;
    
    return data;
  }
  
}

Solution 2:[2]

Try the following, works perfectly well on my side:

  Map<String,dynamic> a = {'a' : 'b', 'c' : {'d' : 'e'}};
  void _go () async  {
    final Directory directory = await getApplicationDocumentsDirectory();
    final File file = File('${directory.path}/a.json');
    await file.writeAsString(json.encode(a));
    Map<String, dynamic> myJson = await json.decode(await file.readAsString());
    print(myJson.toString());
  }


Solution 3:[3]

if you face upload file problem in 2021. the best way to upload file in the rest API or on the local server

     Future<ApiResponse<bool>> uploadfile(File file) async {

    var stream = new http.ByteStream(DelegatingStream(file.openRead()));
    var length = await file.length();
    var uri = Uri.parse("Enter your URL");
    var request = new http.MultipartRequest("POST", uri);
    var multipartFile = new http.MultipartFile('data', stream, length, filename: basename(file.path));
    request.files.add(multipartFile);
    await request.send().then((response) {
      response.stream.transform(utf8.decoder).listen((value) {
      file.delete();
        print(value);
      });

    }).catchError((e) {
      print(e);
    });
  }

code to make a local JSON file

     void makeJsonFile(Map<String, List> value) async 
 {
     final Directory directory = await getApplicationDocumentsDirectory();
     final File file = File('${directory.path}/360feedback.json');
  
     await file.writeAsString(jsonEncode(value));

      RecordService>.uploadfile(file).then((value) {
           
                  });
  }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sadikul Haque Sadi
Solution 2 Antonin GAVREL
Solution 3 benten