Как я могу обновить/добавить новую информацию в свой локальный файл JSOn в Flutter? (без создания каких-либо классов)

#json #flutter #dart

Вопрос:

Я сделал небольшое приложение, что-то вроде библиотечного приложения, в которое вы можете добавлять прочитанные книги. Итак, у меня есть локальный файл JSON, который выглядит следующим образом:

 [
  {
    "name": "Harry Potter and the Deathly Hallows",
    "author": "J.K. Rowling",
    "rating": "4.5",
    "category": "Fantasy",
    "url": "some url"
  },
  {
    "name": "For Whom The Bell Tolls",
    "author": "E. Hemingway",
    "rating": "4",
    "category": "Novel",
    "url": "some url#2"
  }
]
 

В моем основном файле.dart у меня есть функция, которая считывает мой файл JSON, декодирует и загружает его в список с именем «данные».:

 readData(){
    DefaultAssetBundle.of(context).loadString("json/books.json").then((s){
      setState(() {
        data = json.decode(s);
      });

    });
  }

@override
  void initState() {
    super.initState();
    readData();

  }

 

Я могу легко добавлять новые книги в «данные», и все в порядке, за исключением одного — я не знаю, как обновлять/записывать информацию в JSON, поэтому приложение может показать мне обновленный список с новой книгой после перезапуска. Я добавил. Как мне это сделать? И что я должен записать в файл JSON — обновленный список со всеми книгами или просто карту с новой книгой?

Ответ НельсоНтиаго

Этот код находится в «Состоянии расширения класса AddingPageState».:

 Future<String> get _localPath async {
    final directory = await getApplicationDocumentsDirectory();
    return directory.path;
  }
  Future<File> get _localFile async {
    final path = await _localPath;
    return File('$path/books.json');
  }
  Future<File> writeData(List list) async { // "list" is the updated book-list
    final file = await _localFile;
    String encodedData = jsonEncode(list);
    return file.writeAsString('$encodedData');
  }
 

И я вызываю «writeData» в функции onPressed.

Комментарии:

1. Все еще получаете no such directory/file ошибку ??

2. Нет, он просто не записывает/не сохраняет данные в файл JSON. Я не получаю никаких ошибок, новая книга просто исчезает после перезапуска моего приложения

3. Таким образом, в основном мое приложение работает так: 1) на первой странице Я прочитал мой файл JSON в initState() и отобразить книги с полной информацией; 2) также есть floatingActonButton с onPressed() функция которая переводит пользователя на вторую страницу и ожидает Map с информацией о новой книге (что-то вроде final _newBookInfo = await Navigator,push() …). 3) На второй странице есть поля для информации, и кнопки «Подтвердить». Когда вы нажимаете на нее, она создает новую Map , вызывает writeData функцию и возвращается на первую страницу.

4. 4) Затем есть функция, которая добавляет newBook информацию ко List всем книгам и отображает их все. Проблема в том, что когда я перезапускаю приложение, оно показывает мне старый список без новой книги. По-видимому, эта writeData функция не работает.

Ответ №1:

Было бы лучше сделать это с помощью локальной базы данных NoSQL, такой как sembast, таким образом, вы могли бы добавлять, удалять и обновлять свои данные. Но поскольку вы уже работаете с json, вам просто нужно закодировать новое изменение data в json и снова записать в файл. Для записи и чтения файлов вместо использования rootBundle read это чтение и запись файлов.

Комментарии:

1. Я уже пробовал код из статьи FlutterDev раньше, и у меня были ошибки типа «нет такого каталога/файла».

2. Можете ли вы показать код, пытающийся получить доступ к каталогу устройств?

3. Я добавил ответ к своему сообщению

4. Ответил на вопрос под постом.

5. Да, я понимаю, я просто понимаю, почему это не сработает, если все выглядит нормально, вам следует поискать ошибки или распечатать данные, чтобы увидеть, что происходит.

Ответ №2:

Как я вижу из вашего файла JSON, вы храните Книги в виде списка объектов JSON, что упростит задачу.

Но ваша просьба решить эту проблему без добавления новых классов немного странна, потому что добавление класса Book в вашем случае значительно упростило бы задачу.

Поэтому я собираюсь дать вам решение, которое предполагает, что вы создадите новый класс книг.

  1. Начните с чтения файла, как вы делаете это в настоящее время.
  2. Сохраните содержимое файла в списке динамического списка.
  3. Выполните итерацию по списку с помощью функции map, добавьте с помощью функции from JSON в класс Book декодируйте JSON в объект book, затем примените функцию ToList() к этой карте.
  4. Верните результат в свой пользовательский интерфейс и обработайте его как любой другой список.
  5. Если вы хотите добавить новую книгу, создайте новый объект класса book и добавьте его в свой список.
  6. Когда пользователь завершит добавление, преобразуйте список в объект JSON agian и снова сохраните его в файле;

Что-то вроде этого:

 The Book Class:

class Book {
  String? name;
  String? author;
  String? rating;
  String? category;
  String? url;

  Book({
    required this.name,
    required this.author,
   required this.rating,
  required  this.category,
    required this.url,
  });

  Book.fromJson(Map<String, dynamic> json) {
    name = json['name'];
    author = json['author'];
    rating = json['rating'];
    category = json['category'];
    url = json['url'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['name'] = this.name;
    data['author'] = this.author;
    data['rating'] = this.rating;
    data['category'] = this.category;
    data['url'] = this.url;
    return data;
  }
  @override
  String toString() {
    return 'Book(name: $name, author: $author, rating: $rating, category: $category, url: $url)';
  }
}
 

И основная функция

 void main() {
  /// read the file the way you like
  List<dynamic> list = [
    {
      "name": "Harry Potter and the Deathly Hallows",
      "author": "J.K. Rowling",
      "rating": "4.5",
      "category": "Fantasy",
      "url": "some url"
    },
    {
      "name": "For Whom The Bell Tolls",
      "author": "E. Hemingway",
      "rating": "4",
      "category": "Novel",
      "url": "some url#2"
    }
  ];

  List<Book> books = list
      .map(
        (jsonObject) => Book.fromJson(jsonObject),
      )
      .toList();

  print(books);

  Book newBook = Book(
      name: 'Some Book',
      author: 'Some Author',
      rating: 'Some rating',
      category: 'Some category',
      url: 'Some Url');

  books.add(newBook);

  print(books);

  books
      .map(
        (book) => book.toJson(),
      )
      .toList();
  
  //Write the the file again to storage or anywhere else 
}
 

Комментарии:

1. Не могли бы вы прокомментировать свой код и сказать мне, что я должен сделать в первую очередь, потому что я новичок в программировании и на самом деле не понимаю классы.

2. также я получаю «Ненулевое поле экземпляра «имя» должно быть инициализировано» ошибки (то же самое с «автором», «категорией» и другими). Где в коде я могу их инициализировать?

3. О, моя вина, я должен был включить нулевую безопасность на площадке для игры в дартс !! Я обновлю ответ. Но в качестве совета посмотрите это видео о нулевой безопасности, поскольку она становится по умолчанию в проектах flutter ссылка

4. А что касается темы занятий, я предлагаю прочитать и поискать об этом в Интернете, так как это фундаментально в программировании в целом.

5. Спасибо, но я хотел бы знать, как мне записать обновленный список книг обратно в файл JSON. Потому что, когда я перезапускаю приложение, оно просто не показывает мне список с новой книгой. Я предполагаю, что метод «toJSON» возвращает закодированный список книг, но, похоже, он не сохраняет его в моем локальном файле JSON.