#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 в вашем случае значительно упростило бы задачу.
Поэтому я собираюсь дать вам решение, которое предполагает, что вы создадите новый класс книг.
- Начните с чтения файла, как вы делаете это в настоящее время.
- Сохраните содержимое файла в списке динамического списка.
- Выполните итерацию по списку с помощью функции map, добавьте с помощью функции from JSON в класс Book декодируйте JSON в объект book, затем примените функцию ToList() к этой карте.
- Верните результат в свой пользовательский интерфейс и обработайте его как любой другой список.
- Если вы хотите добавить новую книгу, создайте новый объект класса book и добавьте его в свой список.
- Когда пользователь завершит добавление, преобразуйте список в объект 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.