Hassico
Hassico

Reputation: 192

How to write to json files correctly?

I am storing user favorites to json file bu I am getting the following error:

Unhandled Exception: type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>' of 'other'

And I am adding the following data to the file:

{
 3423: {
'ID': 3423,
'Title': 'Jupiter Ascending',
'Image': 'https://...'
}
}

The code is:

File jsonFile;
Directory dir;
String fileName = "Reading.json";
bool fileExists = false;
List<Map> fileContent;

@override
void initState() {
  super.initState();
  /*to store files temporary we use getTemporaryDirectory() but we need
    permanent storage so we use getApplicationDocumentsDirectory() */
  getApplicationDocumentsDirectory().then((Directory directory) {
    dir = directory;
    jsonFile = new File(dir.path + "/" + fileName);
    fileExists = jsonFile.existsSync();
    if (fileExists)
      this.setState(
          () => fileContent = json.decode(jsonFile.readAsStringSync()));
  });
}

void createFile(Map content, Directory dir, String fileName) {
  print("Creating file!");
  File file = new File(dir.path + "/" + fileName);
  file.createSync();
  fileExists = true;
  file.writeAsStringSync(json.encode(content));
}

void writeToFile(var key, var value) {
  print("Writing to file!");
  Map content = {key: value};
  if (fileExists) {
    print("File exists");
    Map jsonFileContent = json.decode(jsonFile.readAsStringSync());
    jsonFileContent.addAll(content);
    jsonFile.writeAsStringSync(json.encode(jsonFileContent));
  } else {
    print("File does not exist!");
    createFile(content, dir, fileName);
  }
  this.setState(() => fileContent = json.decode(jsonFile.readAsStringSync()));
  print(fileContent);
}

I am confused and do not know how to solve the problem.

Upvotes: 0

Views: 773

Answers (1)

julemand101
julemand101

Reputation: 31209

You have removed any traces of typing in your writeToFile method which makes it so Dart cannot help you. The problem comes from:

void writeToFile(var key, var value) {
  print("Writing to file!");
  Map content = {key: value};
...

First, don't ever use var as parameter type on a method. It is really bad because you allow all types which is properly not what you want.

In this case, the result of json.decode(jsonFile.readAsStringSync()) will be a Map<String, dynamic> instance on runtime.

But the Map you are creating with Map content = {key: value}; is going to be of the type Map<dynamic, dynamic> because it cannot predict the types for key and value when compiling the code.

Since you cannot put the content of a Map<dynamic, dynamic> into Map<String, dynamic> you get an error.

What you can do is to make the key at least a String like:

void writeToFile(String key, var value) {
  print("Writing to file!");
  final content = {key: value};
...

I will also say you can help yourself if you are using var and final instead of trying typing the type manually. It is fine if you want the types but then you really need to explicit write the correct generic part of the type.

E.g. this is wrong:

Map jsonFileContent = json.decode(jsonFile.readAsStringSync());

Since you are trowing the generic part away. Instead it should be:

Map<String, dynamic> jsonFileContent = json.decode(jsonFile.readAsStringSync());

Or let Dart handle that stuff with:

final jsonFileContent = json.decode(jsonFile.readAsStringSync());

Upvotes: 1

Related Questions