'Creating a list of objects from a nested JSON in Flutter

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'],
    );
  }
}


  


Solution 1:[1]

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).
????? ??? ???? ??
???? ??? ?????? ?? ??
??"? ?????? ?? ??
??? ????? ?????? ?? ??
??? ??? ???? ?????? ?? ??
?????? ?????? ?? ??
??"? ?????? ?? ??
???? ????? ?????? ?? ??
???? ??? ?????? ?? ??
???"? ?????? ?? ??

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