Home > Back-end >  Creating a list of objects from a nested JSON in Flutter
Creating a list of objects from a nested JSON in Flutter

Time:05-15

There's a URL address that I decoded to JSON, and there's a certain header (result) that I'm trying to convert to a list of objects (Book).
When I print the content of this header I do get the desired result (first print), but when I create the list and try to print one of the fields of the first object in the list nothing is printed (second print).
Which means there's a problem with the way I create the list and I can't find it.
I would really appreciate your help.

The JSON structure:

{count: 9447, result: [{book_about: string, book_label: string, book_wikilink: string, fragments: [string1, string2, string3, string4], id: string, label: string, text: string]}

An image of it: https://i.stack.imgur.com/w2JGm.png

My code:

Future<List<Book>> fetchBooks(http.Client client) async {

  var url = 'http://jbse.cs.technion.ac.il:3030/search?query=אברהם&start=0';
  final response = await http.get(Uri.parse(url),headers: {'Content-Type': 'application/json'});

  Map<String, dynamic> responseBody = jsonDecode(response.body);
  dynamic results = responseBody['result'];
  print(results);

  List<Book> list = results.map((book) => Book.fromJson(book)).toList();
  print(list.first.book_wikilink);
  return list;
}


class Book {
  String book_about;
  String book_label;
  String book_wikilink;
  List<String> fragments;
  String id;
  String label;
  String text;

  Book(
    this.book_about,
    this.book_label,
    this.book_wikilink,
    this.fragments,
    this.id,
    this.label,
    this.text
      );

  factory Book.fromJson(Map<String, dynamic> json) {
    return Book(
      json['book_about'],
      json['book_label'],
      json['book_wikilink'] ,
      json['fragments'],
      json['id'],
      json['label'],
      json['text'],
    );
  }
}


  

CodePudding user response:

You can do it manually.
Select and convert what you want on the fly (during parsing).

import 'package:fast_json/fast_json_selector.dart' as parser;
import 'package:http/http.dart' as http;

void main(List<String> args) async {
  final books = await fetchBooks();
  print('Found: ${books.length} book(s).');
  print(books.map((e) => e.label).join('\n'));
}

Future<List<Book>> fetchBooks() async {
  var url = 'http://jbse.cs.technion.ac.il:3030/search?query=אברהם&start=0';
  final response = await http
      .get(Uri.parse(url), headers: {'Content-Type': 'application/json'});
  return _findBooks(response.body);
}

List<Book> _findBooks(String source) {
  // Path to Book
  // Map => property "result" => List => list index => Map (Book)
  final level = '{} result [] 0 {}'.split(' ').length;
  final books = <Book>[];
  void select(parser.JsonSelectorEvent event) {
    if (event.levels.length == level) {
      final book = Book.fromJson(event.lastValue as Map);
      books.add(book);
      // Freeing the memory allocated for the book
      // because it is no longer needed
      event.lastValue = null;
    }
  }

  parser.parse(source, select: select);
  return books;
}

class Book {
  String book_about;
  String book_label;
  String book_wikilink;
  List<String> fragments;
  String id;
  String label;
  String text;

  Book(this.book_about, this.book_label, this.book_wikilink, this.fragments,
      this.id, this.label, this.text);

  factory Book.fromJson(Map json) {
    return Book(
      json['book_about'] as String,
      json['book_label'] as String,
      json['book_wikilink'] as String,
      (json['fragments'] as List).cast(),
      json['id'] as String,
      json['label'] as String,
      json['text'] as String,
    );
  }
}

Output:

Found: 10 book(s).
קדושת לוי וירא טו
חומת אנך בראשית יז כג
רא"ם בראשית כה יט
אור החיים בראשית כה יט
באר מים חיים בראשית כד לד
חזקוני בראשית כה יט
רש"י בראשית כה יט
שפתי חכמים בראשית יט כט
העמק דבר בראשית לא מב
רמב"ן בראשית כה יט
  • Related