From a84cfe5c02184746cfb866254b0649e3cd003b28 Mon Sep 17 00:00:00 2001
From: h7x4 <h7x4abk3g@protonmail.com>
Date: Sun, 8 May 2022 02:06:45 +0200
Subject: [PATCH] Update to 3.0.0

- Add fromJson factories for all objects
- Make some properties use getters, to reduce redundant data
- Make all objects comparable with the equatable package
- Make all objects immutable with a constant constructor
    as a result of making them comparable
---
 CHANGELOG.md                         |    8 +
 README.md                            |    6 +
 example/api/kanji_search.dart        |    1 +
 example/api/phrase_search.dart       |    1 -
 lib/api.dart                         |    5 +-
 lib/src/example_search.dart          |    7 +-
 lib/src/kanji_search.dart            |   51 +-
 lib/src/objects.dart                 |  624 ++++++++---
 lib/src/phrase_scrape.dart           |    7 +-
 pubspec.yaml                         |    3 +-
 test/example_test_cases/0.json       |  210 +++-
 test/example_test_cases/1.json       |  136 +++
 test/example_test_cases/3.json       | 1528 +++++++++++++++++---------
 test/kanji_test_cases/0.json         |   23 +-
 test/kanji_test_cases/1.json         |   41 +-
 test/kanji_test_cases/2.json         |   19 +-
 test/kanji_test_cases/4.json         |    1 +
 test/kanji_test_cases/7.json         |   37 +-
 test/phrase_scrape_test_cases/0.json |   13 +-
 test/phrase_scrape_test_cases/1.json |    2 +-
 test/phrase_scrape_test_cases/2.json |    8 +
 test/unofficial_jisho_api_test.dart  |   49 +-
 22 files changed, 1882 insertions(+), 898 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4268235..1702813 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+# 3.0.0
+
+- Add fromJson factories for all objects
+- Make some properties use getters, to reduce redundant data
+- Make all objects comparable with the equatable package
+- Make all objects immutable with a constant constructor
+    as a result of making them comparable
+
 # 2.0.4
 
 - Fixed bug where pieces were missing in example sentences
diff --git a/README.md b/README.md
index 11668a5..02aed38 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,7 @@ void main() async {
 
     final data = result.data;
     if (data != null) {
+      print('Kanji: ${data.kanji}');
       print('Taught in: ${data.taughtIn}');
       print('JLPT level: ${data.jlptLevel}');
       print('Newspaper frequency rank: ${data.newspaperFrequencyRank}');
@@ -63,6 +64,7 @@ This outputs the following:
 
 ```
 Found: true
+Kanji: 語
 Taught in: grade 2
 JLPT level: N5
 Newspaper frequency rank: 301
@@ -269,6 +271,10 @@ void main() async {
 }
 ```
 
+## Note on usage with web
+
+Although the library is marked as ok for use with website outputs, you will not be able to reach through the CORS setup of jisho.org. You should set up a backend as a proxy if you want to make a website. See (#3)
+
 ## About
 
 Permission to scrape granted by Jisho's admin Kimtaro: https://jisho.org/forum/54fefc1f6e73340b1f160000-is-there-any-kind-of-search-api
diff --git a/example/api/kanji_search.dart b/example/api/kanji_search.dart
index 015d216..ac195c4 100644
--- a/example/api/kanji_search.dart
+++ b/example/api/kanji_search.dart
@@ -7,6 +7,7 @@ void main() {
 
     final data = result.data;
     if (data != null) {
+      print('Kanji: ${data.kanji}');
       print('Taught in: ${data.taughtIn}');
       print('JLPT level: ${data.jlptLevel}');
       print('Newspaper frequency rank: ${data.newspaperFrequencyRank}');
diff --git a/example/api/phrase_search.dart b/example/api/phrase_search.dart
index b1ae45f..5fd3363 100644
--- a/example/api/phrase_search.dart
+++ b/example/api/phrase_search.dart
@@ -4,7 +4,6 @@ final JsonEncoder encoder = JsonEncoder.withIndent('  ');
 
 void main() {
   jisho.searchForPhrase('日').then((result) {
-  // jisho.searchForPhrase('する').then((result) {
     print(encoder.convert(result));
   });
 }
\ No newline at end of file
diff --git a/lib/api.dart b/lib/api.dart
index 088e770..8f9f8c7 100644
--- a/lib/api.dart
+++ b/lib/api.dart
@@ -53,10 +53,7 @@ Future<PhrasePageScrapeResult> scrapeForPhrase(String phrase) async {
   final uri = uriForPhraseScrape(phrase);
   final response = await http.get(uri);
   if (response.statusCode == 404) {
-    return PhrasePageScrapeResult(
-      query: phrase,
-      found: false,
-    );
+    return PhrasePageScrapeResult(query: phrase);
   }
   return parsePhrasePageData(response.body, phrase);
 }
diff --git a/lib/src/example_search.dart b/lib/src/example_search.dart
index 853b780..5dd3eb2 100644
--- a/lib/src/example_search.dart
+++ b/lib/src/example_search.dart
@@ -147,8 +147,7 @@ ExampleResults parseExamplePageData(String pageHtml, String phrase) {
   final results = divs.map(_parseExampleDiv).toList();
 
   return ExampleResults(
-      query: phrase,
-      found: results.isNotEmpty,
-      results: results,
-      uri: uriForExampleSearch(phrase).toString());
+    query: phrase,
+    results: results,
+  );
 }
diff --git a/lib/src/kanji_search.dart b/lib/src/kanji_search.dart
index 2466966..c196416 100644
--- a/lib/src/kanji_search.dart
+++ b/lib/src/kanji_search.dart
@@ -14,7 +14,8 @@ Uri uriForKanjiSearch(String kanji) {
   return Uri.parse('$scrapeBaseUri${Uri.encodeComponent(kanji)}%23kanji');
 }
 
-String _getUriForStrokeOrderDiagram(String kanji) {
+/// Provides the URI for a stroke order diagram
+String getUriForStrokeOrderDiagram(String kanji) {
   return '$strokeOrderDiagramBaseUri${kanji.codeUnitAt(0)}_frames.png';
 }
 
@@ -155,6 +156,7 @@ List<String> _getParts(String pageHtml) {
   return result;
 }
 
+/// Provides the URI for a SVG image of the kanji
 String _getSvgUri(String pageHtml) {
   var svgRegex = RegExp('\/\/.*?.cloudfront.net\/.*?.svg');
 
@@ -167,7 +169,8 @@ String _getSvgUri(String pageHtml) {
   return 'https:$regexResult';
 }
 
-String _getGifUri(String kanji) {
+/// Provides the URI for a GIF of the kanji stroke order
+String getGifUri(String kanji) {
   final unicodeString = kanji.codeUnitAt(0).toRadixString(16);
   final fileName = '$unicodeString.gif';
   final animationUri =
@@ -212,32 +215,26 @@ String? _getJlptLevel(String pageHtml) {
 
 /// Parses a jisho kanji search page to an object
 KanjiResult parseKanjiPageData(String pageHtml, String kanji) {
-  final result = KanjiResult(
-    query: kanji,
-    found: _containsKanjiGlyph(pageHtml, kanji),
-  );
-
-  if (result.found == false) {
-    return result;
+  if (!_containsKanjiGlyph(pageHtml, kanji)) {
+    return KanjiResult(query: kanji);
   }
 
-  result.data = KanjiResultData(
-    strokeCount: _getStrokeCount(pageHtml),
-    meaning: _getMeaning(pageHtml),
-    strokeOrderDiagramUri: _getUriForStrokeOrderDiagram(kanji),
-    strokeOrderSvgUri: _getSvgUri(pageHtml),
-    strokeOrderGifUri: _getGifUri(kanji),
-    uri: uriForKanjiSearch(kanji).toString(),
-    parts: _getParts(pageHtml),
-    taughtIn: _getTaughtIn(pageHtml),
-    jlptLevel: _getJlptLevel(pageHtml),
-    newspaperFrequencyRank: _getNewspaperFrequencyRank(pageHtml),
-    kunyomi: _getKunyomi(pageHtml),
-    onyomi: _getOnyomi(pageHtml),
-    kunyomiExamples: _getKunyomiExamples(pageHtml),
-    onyomiExamples: _getOnyomiExamples(pageHtml),
-    radical: _getRadical(pageHtml),
+  return KanjiResult(
+    query: kanji,
+    data: KanjiResultData(
+      kanji: kanji,
+      strokeCount: _getStrokeCount(pageHtml),
+      meaning: _getMeaning(pageHtml),
+      strokeOrderSvgUri: _getSvgUri(pageHtml),
+      parts: _getParts(pageHtml),
+      taughtIn: _getTaughtIn(pageHtml),
+      jlptLevel: _getJlptLevel(pageHtml),
+      newspaperFrequencyRank: _getNewspaperFrequencyRank(pageHtml),
+      kunyomi: _getKunyomi(pageHtml),
+      onyomi: _getOnyomi(pageHtml),
+      kunyomiExamples: _getKunyomiExamples(pageHtml),
+      onyomiExamples: _getOnyomiExamples(pageHtml),
+      radical: _getRadical(pageHtml),
+    ),
   );
-
-  return result;
 }
diff --git a/lib/src/objects.dart b/lib/src/objects.dart
index aee5ae8..5f01e99 100644
--- a/lib/src/objects.dart
+++ b/lib/src/objects.dart
@@ -1,138 +1,183 @@
+import 'package:equatable/equatable.dart';
+
+import 'example_search.dart';
+import 'kanji_search.dart';
+
 /* -------------------------------------------------------------------------- */
 /*                       searchForKanji related classes                       */
 /* -------------------------------------------------------------------------- */
 
 /// An example of a word that contains the kanji in question.
-class YomiExample {
+class YomiExample extends Equatable {
   /// The original text of the example.
-  String example;
+  final String example;
 
   /// The reading of the example.
-  String reading;
+  final String reading;
 
   /// The meaning of the example.
-  String meaning;
+  final String meaning;
 
   // ignore: public_member_api_docs
-  YomiExample({
+  const YomiExample({
     required this.example,
     required this.reading,
     required this.meaning,
   });
 
+  // ignore: public_member_api_docs
+  factory YomiExample.fromJson(Map<String, dynamic> json) {
+    return YomiExample(
+      example: json['example'] as String,
+      reading: json['reading'] as String,
+      meaning: json['meaning'] as String,
+    );
+  }
+
   // ignore: public_member_api_docs
   Map<String, String> toJson() => {
         'example': example,
         'reading': reading,
         'meaning': meaning,
       };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object> get props => [example, reading, meaning];
 }
 
 /// Information regarding the radical of a kanji.
-class Radical {
+class Radical extends Equatable {
   /// The radical symbol.
-  String symbol;
+  final String symbol;
 
   /// The radical forms used in this kanji.
-  List<String> forms;
+  final List<String> forms;
 
   /// The meaning of the radical.
-  String meaning;
+  final String meaning;
 
   // ignore: public_member_api_docs
-  Radical({
+  const Radical({
     required this.symbol,
     this.forms = const [],
     required this.meaning,
   });
 
+  // ignore: public_member_api_docs
+  factory Radical.fromJson(Map<String, dynamic> json) {
+    return Radical(
+      symbol: json['symbol'] as String,
+      forms: (json['forms'] as List).map((e) => e as String).toList(),
+      meaning: json['meaning'] as String,
+    );
+  }
+
   // ignore: public_member_api_docs
   Map<String, dynamic> toJson() => {
         'symbol': symbol,
         'forms': forms,
         'meaning': meaning,
       };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object> get props => [symbol, forms, meaning];
 }
 
 /// The main wrapper containing data about the query and whether or not it was successful.
-class KanjiResult {
+class KanjiResult extends Equatable {
   /// True if results were found.
-  String query;
+  final String query;
 
   /// The term that you searched for.
-  bool found;
+  bool get found => data != null;
 
   /// The result data if search was successful.
-  KanjiResultData? data;
+  final KanjiResultData? data;
 
   // ignore: public_member_api_docs
-  KanjiResult({
+  const KanjiResult({
     required this.query,
-    required this.found,
     this.data,
   });
 
   // ignore: public_member_api_docs
-  Map<String, dynamic> toJson() {
-    return {
-      'query': query,
-      'found': found,
-      'data': data,
-    };
+  factory KanjiResult.fromJson(Map<String, dynamic> json) {
+    return KanjiResult(
+      query: json['query'] as String,
+      data:
+          json['data'] != null ? KanjiResultData.fromJson(json['data']) : null,
+    );
   }
+
+  // ignore: public_member_api_docs
+  Map<String, dynamic> toJson() => {
+        'query': query,
+        'found': found,
+        'data': data,
+      };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object?> get props => [query, data];
 }
 
 /// The main kanji data class, collecting all the result information in one place.
-class KanjiResultData {
+class KanjiResultData extends Equatable {
+  /// The kanji symbol
+  final String kanji;
+
   /// The school level that the kanji is taught in, if applicable.
-  String? taughtIn;
+  final String? taughtIn;
 
   /// The lowest JLPT exam that this kanji is likely to appear in, if applicable.
   ///
   /// 'N5' or 'N4' or 'N3' or 'N2' or 'N1'.
-  String? jlptLevel;
+  final String? jlptLevel;
 
   /// A number representing this kanji's frequency rank in newspapers, if applicable.
-  int? newspaperFrequencyRank;
+  final int? newspaperFrequencyRank;
 
   /// How many strokes this kanji is typically drawn in.
-  int strokeCount;
+  final int strokeCount;
 
   /// The meaning of the kanji.
-  String meaning;
+  final String meaning;
 
   /// This character's kunyomi.
-  List<String> kunyomi;
+  final List<String> kunyomi;
 
   /// This character's onyomi.
-  List<String> onyomi;
+  final List<String> onyomi;
 
   /// Examples of this character's kunyomi being used.
-  List<YomiExample> kunyomiExamples;
+  final List<YomiExample> kunyomiExamples;
 
   /// Examples of this character's onyomi being used.
-  List<YomiExample> onyomiExamples;
+  final List<YomiExample> onyomiExamples;
 
   /// Information about this character's radical, if applicable.
-  Radical? radical;
+  final Radical? radical;
 
   /// The parts used in this kanji.
-  List<String> parts;
+  final List<String> parts;
 
   /// The URL to a diagram showing how to draw this kanji step by step.
-  String strokeOrderDiagramUri;
+  String get strokeOrderDiagramUri => getUriForStrokeOrderDiagram(kanji);
 
   /// The URL to an SVG describing how to draw this kanji.
-  String strokeOrderSvgUri;
+  final String strokeOrderSvgUri;
 
   ///  The URL to a gif showing the kanji being draw and its stroke order.
-  String strokeOrderGifUri;
+  String get strokeOrderGifUri => getGifUri(kanji);
 
   /// The URI that these results were scraped from.
-  String uri;
+  String get uri => uriForKanjiSearch(kanji).toString();
 
   // ignore: public_member_api_docs
-  KanjiResultData({
+  const KanjiResultData({
+    required this.kanji,
     this.taughtIn,
     this.jlptLevel,
     this.newspaperFrequencyRank,
@@ -144,32 +189,69 @@ class KanjiResultData {
     this.onyomiExamples = const [],
     this.radical,
     this.parts = const [],
-    required this.strokeOrderDiagramUri,
     required this.strokeOrderSvgUri,
-    required this.strokeOrderGifUri,
-    required this.uri,
   });
 
   // ignore: public_member_api_docs
-  Map<String, dynamic> toJson() {
-    return {
-      'taughtIn': taughtIn,
-      'jlptLevel': jlptLevel,
-      'newspaperFrequencyRank': newspaperFrequencyRank,
-      'strokeCount': strokeCount,
-      'meaning': meaning,
-      'kunyomi': kunyomi,
-      'onyomi': onyomi,
-      'onyomiExamples': onyomiExamples,
-      'kunyomiExamples': kunyomiExamples,
-      'radical': radical?.toJson(),
-      'parts': parts,
-      'strokeOrderDiagramUri': strokeOrderDiagramUri,
-      'strokeOrderSvgUri': strokeOrderSvgUri,
-      'strokeOrderGifUri': strokeOrderGifUri,
-      'uri': uri,
-    };
+  factory KanjiResultData.fromJson(Map<String, dynamic> json) {
+    return KanjiResultData(
+      kanji: json['kanji'] as String,
+      taughtIn: json['taughtIn'] as String?,
+      jlptLevel: json['jlptLevel'] as String?,
+      newspaperFrequencyRank: json['newspaperFrequencyRank'] as int?,
+      strokeCount: json['strokeCount'] as int,
+      meaning: json['meaning'] as String,
+      kunyomi: (json['kunyomi'] as List).map((e) => e as String).toList(),
+      onyomi: (json['onyomi'] as List).map((e) => e as String).toList(),
+      kunyomiExamples: (json['kunyomiExamples'] as List)
+          .map((e) => YomiExample.fromJson(e))
+          .toList(),
+      onyomiExamples: (json['onyomiExamples'] as List)
+          .map((e) => YomiExample.fromJson(e))
+          .toList(),
+      radical:
+          json['radical'] != null ? Radical.fromJson(json['radical']) : null,
+      parts: (json['parts'] as List).map((e) => e as String).toList(),
+      strokeOrderSvgUri: json['strokeOrderSvgUri'] as String,
+    );
   }
+
+  // ignore: public_member_api_docs
+  Map<String, dynamic> toJson() => {
+        'kanji': kanji,
+        'taughtIn': taughtIn,
+        'jlptLevel': jlptLevel,
+        'newspaperFrequencyRank': newspaperFrequencyRank,
+        'strokeCount': strokeCount,
+        'meaning': meaning,
+        'kunyomi': kunyomi,
+        'onyomi': onyomi,
+        'onyomiExamples': onyomiExamples,
+        'kunyomiExamples': kunyomiExamples,
+        'radical': radical?.toJson(),
+        'parts': parts,
+        'strokeOrderDiagramUri': strokeOrderDiagramUri,
+        'strokeOrderSvgUri': strokeOrderSvgUri,
+        'strokeOrderGifUri': strokeOrderGifUri,
+        'uri': uri,
+      };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object?> get props => [
+        taughtIn,
+        jlptLevel,
+        newspaperFrequencyRank,
+        strokeCount,
+        meaning,
+        kunyomi,
+        onyomi,
+        kunyomiExamples,
+        onyomiExamples,
+        radical,
+        parts,
+        strokeOrderSvgUri,
+      ];
 }
 
 /* -------------------------------------------------------------------------- */
@@ -177,19 +259,27 @@ class KanjiResultData {
 /* -------------------------------------------------------------------------- */
 
 /// A word in an example sentence, consisting of either just kana, or kanji with furigana.
-class ExampleSentencePiece {
+class ExampleSentencePiece extends Equatable {
   /// Furigana text shown on Jisho.org (above the unlifted text), if applicable.
-  String? lifted;
+  final String? lifted;
 
   /// Baseline text shown on Jisho.org (below the lifted text / furigana).
-  String unlifted;
+  final String unlifted;
 
   // ignore: public_member_api_docs
-  ExampleSentencePiece({
+  const ExampleSentencePiece({
     this.lifted,
     required this.unlifted,
   });
 
+  // ignore: public_member_api_docs
+  factory ExampleSentencePiece.fromJson(Map<String, dynamic> json) {
+    return ExampleSentencePiece(
+      lifted: json['lifted'] as String?,
+      unlifted: json['unlifted'] as String,
+    );
+  }
+
   // ignore: public_member_api_docs
   Map<String, dynamic> toJson() {
     return {
@@ -197,30 +287,44 @@ class ExampleSentencePiece {
       'unlifted': unlifted,
     };
   }
+
+  List<Object?> get props => [lifted, unlifted];
 }
 
 /// All data making up one example sentence.
-class ExampleResultData {
+class ExampleResultData extends Equatable {
   /// The example sentence including kanji.
-  String kanji;
+  final String kanji;
 
   /// The example sentence without kanji (only kana). Sometimes this may include some Kanji, as furigana is not always available from Jisho.org.
-  String kana;
+  final String kana;
 
   /// An English translation of the example.
-  String english;
+  final String english;
 
   /// The lifted/unlifted pairs that make up the sentence. Lifted text is furigana, unlifted is the text below the furigana.
-  List<ExampleSentencePiece> pieces;
+  final List<ExampleSentencePiece> pieces;
 
   // ignore: public_member_api_docs
-  ExampleResultData({
+  const ExampleResultData({
     required this.english,
     required this.kanji,
     required this.kana,
     required this.pieces,
   });
 
+  // ignore: public_member_api_docs
+  factory ExampleResultData.fromJson(Map<String, dynamic> json) {
+    return ExampleResultData(
+      english: json['english'] as String,
+      kanji: json['kanji'] as String,
+      kana: json['kana'] as String,
+      pieces: (json['pieces'] as List)
+          .map((e) => ExampleSentencePiece.fromJson(e))
+          .toList(),
+    );
+  }
+
   // ignore: public_member_api_docs
   Map<String, dynamic> toJson() {
     return {
@@ -230,30 +334,40 @@ class ExampleResultData {
       'pieces': pieces,
     };
   }
+
+  List<Object> get props => [english, kanji, kana, pieces];
 }
 
 /// The main wrapper containing data about the query and whether or not it was successful.
-class ExampleResults {
+class ExampleResults extends Equatable {
   /// The term that you searched for.
-  String query;
+  final String query;
 
   /// True if results were found.
-  bool found;
+  bool get found => results.isNotEmpty;
 
   /// The URI that these results were scraped from.
-  String uri;
+  String get uri => uriForExampleSearch(query).toString();
 
   /// The examples that were found, if any.
-  List<ExampleResultData> results;
+  final List<ExampleResultData> results;
 
   // ignore: public_member_api_docs
-  ExampleResults({
+  const ExampleResults({
     required this.query,
-    required this.found,
     required this.results,
-    required this.uri,
   });
 
+  // ignore: public_member_api_docs
+  factory ExampleResults.fromJson(Map<String, dynamic> json) {
+    return ExampleResults(
+      query: json['query'] as String,
+      results: (json['results'] as List)
+          .map((e) => ExampleResultData.fromJson(e))
+          .toList(),
+    );
+  }
+
   // ignore: public_member_api_docs
   Map<String, dynamic> toJson() {
     return {
@@ -263,6 +377,8 @@ class ExampleResults {
       'uri': uri,
     };
   }
+
+  List<Object> get props => [query, results];
 }
 
 /* -------------------------------------------------------------------------- */
@@ -270,52 +386,70 @@ class ExampleResults {
 /* -------------------------------------------------------------------------- */
 
 /// An example sentence.
-class PhraseScrapeSentence {
+class PhraseScrapeSentence extends Equatable {
   /// The English meaning of the sentence.
-  String english;
+  final String english;
 
   /// The Japanese text of the sentence.
-  String japanese;
+  final String japanese;
 
   /// The lifted/unlifted pairs that make up the sentence. Lifted text is furigana, unlifted is the text below the furigana.
-  List<ExampleSentencePiece> pieces;
+  final List<ExampleSentencePiece> pieces;
 
   // ignore: public_member_api_docs
-  PhraseScrapeSentence({
+  const PhraseScrapeSentence({
     required this.english,
     required this.japanese,
     required this.pieces,
   });
 
   // ignore: public_member_api_docs
-  Map<String, dynamic> toJson() =>
-      {'english': english, 'japanese': japanese, 'pieces': pieces};
+  factory PhraseScrapeSentence.fromJson(Map<String, dynamic> json) {
+    return PhraseScrapeSentence(
+      english: json['english'] as String,
+      japanese: json['japanese'] as String,
+      pieces: (json['pieces'] as List)
+          .map((e) => ExampleSentencePiece.fromJson(e))
+          .toList(),
+    );
+  }
+
+  // ignore: public_member_api_docs
+  Map<String, dynamic> toJson() => {
+        'english': english,
+        'japanese': japanese,
+        'pieces': pieces,
+      };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object> get props => [english, japanese, pieces];
 }
 
 /// The data representing one "meaning" or "sense" of the word
-class PhraseScrapeMeaning {
+class PhraseScrapeMeaning extends Equatable {
   /// The words that Jisho lists as "see also".
-  List<String> seeAlsoTerms;
+  final List<String> seeAlsoTerms;
 
   /// Example sentences for this meaning.
-  List<PhraseScrapeSentence> sentences;
+  final List<PhraseScrapeSentence> sentences;
 
   /// The definition of the meaning.
-  String definition;
+  final String definition;
 
   /// Supplemental information.
   /// For example "usually written using kana alone".
-  List<String> supplemental;
+  final List<String> supplemental;
 
   /// An "abstract" definition.
   /// Often this is a Wikipedia definition.
-  String? definitionAbstract;
+  final String? definitionAbstract;
 
   /// Tags associated with this meaning.
-  List<String> tags;
+  final List<String> tags;
 
   // ignore: public_member_api_docs
-  PhraseScrapeMeaning({
+  const PhraseScrapeMeaning({
     this.seeAlsoTerms = const [],
     required this.sentences,
     required this.definition,
@@ -324,6 +458,22 @@ class PhraseScrapeMeaning {
     this.tags = const [],
   });
 
+  // ignore: public_member_api_docs
+  factory PhraseScrapeMeaning.fromJson(Map<String, dynamic> json) {
+    return PhraseScrapeMeaning(
+      seeAlsoTerms:
+          (json['seeAlsoTerms'] as List).map((e) => e as String).toList(),
+      sentences: (json['sentences'] as List)
+          .map((e) => PhraseScrapeSentence.fromJson(e))
+          .toList(),
+      definition: json['definition'] as String,
+      supplemental:
+          (json['supplemental'] as List).map((e) => e as String).toList(),
+      definitionAbstract: json['definitionAbstract'] as String?,
+      tags: (json['tags'] as List).map((e) => e as String).toList(),
+    );
+  }
+
   // ignore: public_member_api_docs
   Map<String, dynamic> toJson() => {
         'seeAlsoTerms': seeAlsoTerms,
@@ -333,98 +483,146 @@ class PhraseScrapeMeaning {
         'definitionAbstract': definitionAbstract,
         'tags': tags,
       };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object?> get props => [
+        seeAlsoTerms,
+        sentences,
+        definition,
+        supplemental,
+        definitionAbstract,
+        tags
+      ];
 }
 
 /// A pair of kanji and potential furigana.
-class KanjiKanaPair {
+class KanjiKanaPair extends Equatable {
   /// Kanji
-  String kanji;
+  final String kanji;
 
   /// Furigana, if applicable.
-  String? kana;
+  final String? kana;
 
   // ignore: public_member_api_docs
-  KanjiKanaPair({
+  const KanjiKanaPair({
     required this.kanji,
     this.kana,
   });
 
+  // ignore: public_member_api_docs
+  factory KanjiKanaPair.fromJson(Map<String, dynamic> json) {
+    return KanjiKanaPair(
+      kanji: json['kanji'] as String,
+      kana: json['kana'] as String?,
+    );
+  }
+
   // ignore: public_member_api_docs
   Map<String, dynamic> toJson() => {
         'kanji': kanji,
         'kana': kana,
       };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object?> get props => [kanji, kana];
 }
 
 /// The main wrapper containing data about the query and whether or not it was successful.
-class PhrasePageScrapeResult {
+class PhrasePageScrapeResult extends Equatable {
   /// True if a result was found.
-  bool found;
+  bool get found => data != null;
 
   /// The term that you searched for.
-  String query;
+  final String query;
 
   /// The result data if search was successful.
-  PhrasePageScrapeResultData? data;
+  final PhrasePageScrapeResultData? data;
 
   // ignore: public_member_api_docs
-  PhrasePageScrapeResult({
-    required this.found,
+  const PhrasePageScrapeResult({
     required this.query,
     this.data,
   });
 
+  // ignore: public_member_api_docs
+  factory PhrasePageScrapeResult.fromJson(Map<String, dynamic> json) {
+    return PhrasePageScrapeResult(
+      query: json['query'] as String,
+      data: json['data'] != null
+          ? PhrasePageScrapeResultData.fromJson(json['data'])
+          : null,
+    );
+  }
+
   // ignore: public_member_api_docs
   Map<String, dynamic> toJson() => {
         'found': found,
         'query': query,
         'data': data,
       };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object?> get props => [query, data];
 }
 
 /// Pronounciation audio.
-class AudioFile {
+class AudioFile extends Equatable {
   /// The uri of the audio file.
-  String uri;
+  final String uri;
 
   /// The mimetype of the audio.
-  String mimetype;
+  final String mimetype;
 
   // ignore: public_member_api_docs
-  AudioFile({
+  const AudioFile({
     required this.uri,
     required this.mimetype,
   });
 
+  // ignore: public_member_api_docs
+  factory AudioFile.fromJson(Map<String, dynamic> json) {
+    return AudioFile(
+      uri: json['uri'] as String,
+      mimetype: json['mimetype'] as String,
+    );
+  }
+
   // ignore: public_member_api_docs
   Map<String, dynamic> toJson() => {
         'uri': uri,
         'mimetype': mimetype,
       };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object> get props => [uri, mimetype];
 }
 
 /// The main scrape data class, collecting all the result information in one place.
-class PhrasePageScrapeResultData {
+class PhrasePageScrapeResultData extends Equatable {
   /// The URI that these results were scraped from.
-  String uri;
+  final String uri;
 
   /// Other forms of the search term.
-  List<String> tags;
+  final List<String> tags;
 
   /// Information about the meanings associated with this search result.
-  List<PhraseScrapeMeaning> meanings;
+  final List<PhraseScrapeMeaning> meanings;
 
   /// Tags associated with this search result.
-  List<KanjiKanaPair> otherForms;
+  final List<KanjiKanaPair> otherForms;
 
   /// Pronounciation of the search result.
-  List<AudioFile> audio;
+  final List<AudioFile> audio;
 
   /// Notes associated with the search result.
-  List<String> notes;
+  final List<String> notes;
 
   // ignore: public_member_api_docs
-  PhrasePageScrapeResultData({
+  const PhrasePageScrapeResultData({
     required this.uri,
     this.tags = const [],
     this.meanings = const [],
@@ -433,6 +631,22 @@ class PhrasePageScrapeResultData {
     this.notes = const [],
   });
 
+  // ignore: public_member_api_docs
+  factory PhrasePageScrapeResultData.fromJson(Map<String, dynamic> json) {
+    return PhrasePageScrapeResultData(
+      uri: json['uri'] as String,
+      tags: (json['tags'] as List).map((e) => e as String).toList(),
+      meanings: (json['meanings'] as List)
+          .map((e) => PhraseScrapeMeaning.fromJson(e))
+          .toList(),
+      otherForms: (json['otherForms'] as List)
+          .map((e) => KanjiKanaPair.fromJson(e))
+          .toList(),
+      audio: (json['audio'] as List).map((e) => AudioFile.fromJson(e)).toList(),
+      notes: (json['notes'] as List).map((e) => e as String).toList(),
+    );
+  }
+
   // ignore: public_member_api_docs
   Map<String, dynamic> toJson() => {
         'uri': uri,
@@ -442,6 +656,10 @@ class PhrasePageScrapeResultData {
         'audio': audio,
         'notes': notes,
       };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object> get props => [uri, tags, meanings, otherForms, audio, notes];
 }
 
 /* -------------------------------------------------------------------------- */
@@ -451,18 +669,18 @@ class PhrasePageScrapeResultData {
 /// Kanji/Furigana pair, or just kana as word.
 ///
 /// Which field acts as kanji and/or kana might be unreliable, which is why both are nullable.
-class JishoJapaneseWord {
+class JishoJapaneseWord extends Equatable {
   /// Usually kanji or kana.
-  String? word;
+  final String? word;
 
   /// Usually furigana, if applicable.
-  String? reading;
+  final String? reading;
 
   // ignore: public_member_api_docs
-  JishoJapaneseWord({
+  const JishoJapaneseWord({
     this.word,
     this.reading,
-  });
+  }) : assert(word != null || reading != null);
 
   // ignore: public_member_api_docs
   factory JishoJapaneseWord.fromJson(Map<String, dynamic> json) {
@@ -477,18 +695,22 @@ class JishoJapaneseWord {
         'word': word,
         'reading': reading,
       };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object?> get props => [word, reading];
 }
 
 /// Relevant links of the search result.
-class JishoSenseLink {
+class JishoSenseLink extends Equatable {
   /// Description of the linked webpage.
-  String text;
+  final String text;
 
   /// Link to the webpage.
-  String url;
+  final String url;
 
   // ignore: public_member_api_docs
-  JishoSenseLink({required this.text, required this.url});
+  const JishoSenseLink({required this.text, required this.url});
 
   // ignore: public_member_api_docs
   factory JishoSenseLink.fromJson(Map<String, dynamic> json) {
@@ -503,18 +725,22 @@ class JishoSenseLink {
         'text': text,
         'url': url,
       };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object> get props => [text, url];
 }
 
 /// Origin of the word (from other languages).
-class JishoWordSource {
+class JishoWordSource extends Equatable {
   /// Origin language.
-  String language;
+  final String language;
 
   /// Origin word, if present.
-  String? word;
+  final String? word;
 
   // ignore: public_member_api_docs
-  JishoWordSource({
+  const JishoWordSource({
     required this.language,
     this.word,
   });
@@ -532,39 +758,43 @@ class JishoWordSource {
         'language:': language,
         'word': word,
       };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object?> get props => [language, word];
 }
 
 /// One sense of the word.
-class JishoWordSense {
+class JishoWordSense extends Equatable {
   /// The meaning(s) of the word.
-  List<String> englishDefinitions;
+  final List<String> englishDefinitions;
 
   /// Type of word (Noun, Verb, etc.).
-  List<String> partsOfSpeech;
+  final List<String> partsOfSpeech;
 
   /// Relevant links.
-  List<JishoSenseLink> links;
+  final List<JishoSenseLink> links;
 
   /// Relevant tags.
-  List<String> tags;
+  final List<String> tags;
 
   /// Relevant words (might include synonyms).
-  List<String> seeAlso;
+  final List<String> seeAlso;
 
   /// Words with opposite meaning.
-  List<String> antonyms;
+  final List<String> antonyms;
 
   /// Origins of the word (from other languages).
-  List<JishoWordSource> source;
+  final List<JishoWordSource> source;
 
   /// Additional info.
-  List<String> info;
+  final List<String> info;
 
   /// Restrictions as to which variants of the japanese words are usable for this sense.
-  List<String> restrictions;
+  final List<String> restrictions;
 
   // ignore: public_member_api_docs
-  JishoWordSense({
+  const JishoWordSense({
     required this.englishDefinitions,
     required this.partsOfSpeech,
     this.links = const [],
@@ -580,26 +810,22 @@ class JishoWordSense {
   factory JishoWordSense.fromJson(Map<String, dynamic> json) {
     return JishoWordSense(
       englishDefinitions: (json['english_definitions'] as List)
-          .map((result) => result as String)
-          .toList(),
-      partsOfSpeech: (json['parts_of_speech'] as List)
-          .map((result) => result as String)
+          .map((e) => e as String)
           .toList(),
+      partsOfSpeech:
+          (json['parts_of_speech'] as List).map((e) => e as String).toList(),
       links: (json['links'] as List)
-          .map((result) => JishoSenseLink.fromJson(result))
+          .map((e) => JishoSenseLink.fromJson(e))
           .toList(),
-      tags: (json['tags'] as List).map((result) => result as String).toList(),
-      seeAlso:
-          (json['see_also'] as List).map((result) => result as String).toList(),
-      antonyms:
-          (json['antonyms'] as List).map((result) => result as String).toList(),
+      tags: (json['tags'] as List).map((e) => e as String).toList(),
+      seeAlso: (json['see_also'] as List).map((e) => e as String).toList(),
+      antonyms: (json['antonyms'] as List).map((e) => e as String).toList(),
       source: (json['source'] as List)
-          .map((result) => JishoWordSource.fromJson(result))
-          .toList(),
-      info: (json['info'] as List).map((result) => result as String).toList(),
-      restrictions: (json['restrictions'] as List)
-          .map((result) => result as String)
+          .map((e) => JishoWordSource.fromJson(e))
           .toList(),
+      info: (json['info'] as List).map((e) => e as String).toList(),
+      restrictions:
+          (json['restrictions'] as List).map((e) => e as String).toList(),
     );
   }
 
@@ -615,21 +841,35 @@ class JishoWordSense {
         'info': info,
         'restrictions': restrictions
       };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object> get props => [
+        englishDefinitions,
+        partsOfSpeech,
+        links,
+        tags,
+        seeAlso,
+        antonyms,
+        source,
+        info,
+        restrictions,
+      ];
 }
 
 /// The original source(s) of the result.
-class JishoAttribution {
+class JishoAttribution extends Equatable {
   /// Whether jmdict was a source.
-  bool jmdict;
+  final bool jmdict;
 
   /// Whether jmnedict was a source.
-  bool jmnedict;
+  final bool jmnedict;
 
   /// Additional sources, if applicable.
-  String? dbpedia;
+  final String? dbpedia;
 
   // ignore: public_member_api_docs
-  JishoAttribution({
+  const JishoAttribution({
     required this.jmdict,
     required this.jmnedict,
     this.dbpedia,
@@ -652,38 +892,42 @@ class JishoAttribution {
         'jmnedict': jmnedict,
         'dbpedia': dbpedia,
       };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object?> get props => [jmdict, jmnedict, dbpedia];
 }
 
 /// The main API data class, collecting all information of one result in one place.
-class JishoResult {
+class JishoResult extends Equatable {
   /// The main version of the word
   ///
   /// This value might sometimes appear as some kind of hash or encoded version of the word.
   /// Whenever it happens, the word usually originates taken from dbpedia
-  String slug;
+  final String slug;
 
   /// Whether the word is common.
   ///
   /// Dbpedia sometimes omit this value.
-  bool? isCommon;
+  final bool? isCommon;
 
   /// Related tags.
-  List<String> tags;
+  final List<String> tags;
 
   /// Relevant jlpt levels.
-  List<String> jlpt;
+  final List<String> jlpt;
 
   /// Japanese versions of the word.
-  List<JishoJapaneseWord> japanese;
+  final List<JishoJapaneseWord> japanese;
 
   /// Translations of the word.
-  List<JishoWordSense> senses;
+  final List<JishoWordSense> senses;
 
   /// Sources.
-  JishoAttribution attribution;
+  final JishoAttribution attribution;
 
   // ignore: public_member_api_docs
-  JishoResult({
+  const JishoResult({
     required this.slug,
     required this.isCommon,
     this.tags = const [],
@@ -698,13 +942,13 @@ class JishoResult {
     return JishoResult(
       slug: json['slug'] as String,
       isCommon: json['is_common'] as bool?,
-      tags: (json['tags'] as List).map((result) => result as String).toList(),
-      jlpt: (json['jlpt'] as List).map((result) => result as String).toList(),
+      tags: (json['tags'] as List).map((e) => e as String).toList(),
+      jlpt: (json['jlpt'] as List).map((e) => e as String).toList(),
       japanese: (json['japanese'] as List)
-          .map((result) => JishoJapaneseWord.fromJson(result))
+          .map((e) => JishoJapaneseWord.fromJson(e))
           .toList(),
       senses: (json['senses'] as List)
-          .map((result) => JishoWordSense.fromJson(result))
+          .map((e) => JishoWordSense.fromJson(e))
           .toList(),
       attribution: JishoAttribution.fromJson(json['attribution']),
     );
@@ -720,15 +964,27 @@ class JishoResult {
         'senses': senses,
         'attribution': attribution,
       };
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object?> get props => [
+        slug,
+        isCommon,
+        tags,
+        jlpt,
+        japanese,
+        senses,
+        attribution,
+      ];
 }
 
 /// Metadata with result status.
-class JishoResultMeta {
+class JishoResultMeta extends Equatable {
   /// HTTP status code.
-  int status;
+  final int status;
 
   // ignore: public_member_api_docs
-  JishoResultMeta({required this.status});
+  const JishoResultMeta({required this.status});
 
   // ignore: public_member_api_docs
   factory JishoResultMeta.fromJson(Map<String, dynamic> json) {
@@ -737,18 +993,22 @@ class JishoResultMeta {
 
   // ignore: public_member_api_docs
   Map<String, dynamic> toJson() => {'status': status};
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object> get props => [status];
 }
 
 /// The main API result wrapper containing whether it was successful, and potential results.
-class JishoAPIResult {
+class JishoAPIResult extends Equatable {
   /// Metadata with result status.
-  JishoResultMeta meta;
+  final JishoResultMeta meta;
 
   /// Results.
-  List<JishoResult>? data;
+  final List<JishoResult>? data;
 
   // ignore: public_member_api_docs
-  JishoAPIResult({
+  const JishoAPIResult({
     required this.meta,
     this.data,
   });
@@ -758,10 +1018,14 @@ class JishoAPIResult {
     return JishoAPIResult(
         meta: JishoResultMeta.fromJson(json['meta']),
         data: (json['data'] as List)
-            .map((result) => JishoResult.fromJson(result))
+            .map((e) => JishoResult.fromJson(e))
             .toList());
   }
 
   // ignore: public_member_api_docs
   Map<String, dynamic> toJson() => {'meta': meta.toJson(), 'data': data};
+
+  @override
+  // ignore: public_member_api_docs
+  List<Object?> get props => [meta, data];
 }
diff --git a/lib/src/phrase_scrape.dart b/lib/src/phrase_scrape.dart
index a7144ca..dccf381 100644
--- a/lib/src/phrase_scrape.dart
+++ b/lib/src/phrase_scrape.dart
@@ -190,14 +190,11 @@ PhrasePageScrapeResult parsePhrasePageData(String pageHtml, String query) {
   final document = parse(pageHtml);
 
   if (!_resultWasFound(document)) {
-    return PhrasePageScrapeResult(found: false, query: query);
+    return PhrasePageScrapeResult(query: query);
   }
 
-  final data = _getMeaningsOtherFormsAndNotes(query, document);
-
   return PhrasePageScrapeResult(
-    found: true,
     query: query,
-    data: data,
+    data: _getMeaningsOtherFormsAndNotes(query, document),
   );
 }
diff --git a/pubspec.yaml b/pubspec.yaml
index 2ba8d87..88690cd 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: unofficial_jisho_api
-version: 2.0.4
+version: 3.0.0
 
 description: An unofficial api for searching and scraping the japanese dictionary Jisho.org
 homepage: https://github.com/h7x4ABk3g/unofficial_jisho_api_dart/
@@ -12,6 +12,7 @@ dependencies:
   http: ^0.13.3
   html_unescape: ^2.0.0
   html: ^0.15.0
+  equatable: ^2.0.3
 
 dev_dependencies:
   lints: ^1.0.1
diff --git a/test/example_test_cases/0.json b/test/example_test_cases/0.json
index d73d553..4aa7beb 100644
--- a/test/example_test_cases/0.json
+++ b/test/example_test_cases/0.json
@@ -2,70 +2,15 @@
   "query": "車",
   "found": true,
   "results": [
-    {
-      "english": "If we can't get the money in any other way, we can, as a last resort, sell the car.",
-      "kanji": "他の方法でお金がつくれなければ最後の手段として車を売り払えばよい。",
-      "kana": "ほかのほうほうでおかねがつくれなければさいごのしゅだんとしてくるまをうりはらえばよい。",
-      "pieces": [
-        {
-          "lifted": "ほか",
-          "unlifted": "他の"
-        },
-        {
-          "lifted": "ほうほう",
-          "unlifted": "方法"
-        },
-        {
-          "lifted": null,
-          "unlifted": "で"
-        },
-        {
-          "lifted": "おかね",
-          "unlifted": "お金"
-        },
-        {
-          "lifted": null,
-          "unlifted": "が"
-        },
-        {
-          "lifted": null,
-          "unlifted": "つくれ"
-        },
-        {
-          "lifted": null,
-          "unlifted": "なければ"
-        },
-        {
-          "lifted": "さいごのしゅだん",
-          "unlifted": "最後の手段"
-        },
-        {
-          "lifted": null,
-          "unlifted": "として"
-        },
-        {
-          "lifted": "くるま",
-          "unlifted": "車"
-        },
-        {
-          "lifted": null,
-          "unlifted": "を"
-        },
-        {
-          "lifted": "うりはら",
-          "unlifted": "売り払えば"
-        },
-        {
-          "lifted": null,
-          "unlifted": "よい"
-        }
-      ]
-    },
     {
       "english": "Any car will do, as long as it runs.",
       "kanji": "走りさえすれば、どんな車でもよいのです。",
       "kana": "はしりさえすれば、どんなくるまでもよいのです。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "はし",
           "unlifted": "走り"
@@ -74,6 +19,10 @@
           "lifted": null,
           "unlifted": "さえすれば"
         },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
         {
           "lifted": null,
           "unlifted": "どんな"
@@ -101,6 +50,10 @@
       "kanji": "窓の外を見ると、車が1台来るのが見えた。",
       "kana": "まどのそとをみると、くるまがいちだいきたるのがみえた。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "まど",
           "unlifted": "窓"
@@ -125,6 +78,10 @@
           "lifted": null,
           "unlifted": "と"
         },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
         {
           "lifted": "くるま",
           "unlifted": "車"
@@ -160,6 +117,10 @@
       "kanji": "素敵な車じゃない。ずいぶん高かっただろう?",
       "kana": "すてきなくるまじゃない。ずいぶんたかかっただろう?",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "すてき",
           "unlifted": "素敵な"
@@ -172,6 +133,10 @@
           "lifted": null,
           "unlifted": "じゃない"
         },
+        {
+          "lifted": null,
+          "unlifted": "。"
+        },
         {
           "lifted": null,
           "unlifted": "ずいぶん"
@@ -191,6 +156,10 @@
       "kanji": "祖母は列車で旅行をするのが好きだ。",
       "kana": "そぼはれっしゃでりょこうをするのがすきだ。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "そぼ",
           "unlifted": "祖母"
@@ -242,6 +211,10 @@
       "kanji": "全員その車に乗った。",
       "kana": "ぜんいんそのくるまにのった。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "ぜんいん",
           "unlifted": "全員"
@@ -269,6 +242,10 @@
       "kanji": "前方に赤い車が見える。",
       "kana": "ぜんぽうにあかいくるまがみえる。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "ぜんぽう",
           "unlifted": "前方"
@@ -300,6 +277,10 @@
       "kanji": "前の車は10年以上持っていた。",
       "kana": "まえのくるまは10ねんいじょうもっていた。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "まえ",
           "unlifted": "前"
@@ -316,6 +297,10 @@
           "lifted": null,
           "unlifted": "は"
         },
+        {
+          "lifted": null,
+          "unlifted": "10"
+        },
         {
           "lifted": "ねん",
           "unlifted": "年"
@@ -335,6 +320,10 @@
       "kanji": "船で旅行するのは車で旅行するよりも時間がかかる。",
       "kana": "ふねでりょこうするのはくるまでりょこうするよりもじかんがかかる。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "ふね",
           "unlifted": "船"
@@ -390,6 +379,10 @@
       "kanji": "線路の上に鉄片があったために列車は脱線した。",
       "kana": "せんろのうえにてっぺんがあったためにれっしゃはだっせんした。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "せんろ",
           "unlifted": "線路"
@@ -445,10 +438,18 @@
       "kanji": "洗えば、車は太陽の光をあびて輝くだろう。",
       "kana": "あらえば、くるまはたいようのひかりをあびてかがやくだろう。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "あら",
           "unlifted": "洗えば"
         },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
         {
           "lifted": "くるま",
           "unlifted": "車"
@@ -492,6 +493,10 @@
       "kanji": "戦車や飛行機は軍隊を打ち破ることはできようが、国民を征服することはできない。",
       "kana": "せんしゃやひこうきはぐんたいをうちやぶることはできようが、こくみんをせいふくすることはできない。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "せんしゃ",
           "unlifted": "戦車"
@@ -536,6 +541,10 @@
           "lifted": null,
           "unlifted": "が"
         },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
         {
           "lifted": "こくみん",
           "unlifted": "国民"
@@ -563,6 +572,10 @@
       "kanji": "先生は新しい車が気に入っている。",
       "kana": "せんせいはあたらしいくるまがきにっている。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "せんせい",
           "unlifted": "先生"
@@ -594,6 +607,10 @@
       "kanji": "先生は私の家まで車で送ってくれた。",
       "kana": "せんせいはわたしのいえまでくるまでおくってくれた。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "せんせい",
           "unlifted": "先生"
@@ -637,6 +654,10 @@
       "kanji": "仙台行きの列車は出たばかりです。",
       "kana": "仙台いきのれっしゃはでたばかりです。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      仙台"
+        },
         {
           "lifted": "い",
           "unlifted": "行き"
@@ -672,6 +693,10 @@
       "kanji": "雪のため列車は走れなかった。",
       "kana": "ゆきのためれっしゃははしれなかった。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "ゆき",
           "unlifted": "雪"
@@ -703,6 +728,10 @@
       "kanji": "雪のため、列車が遅れた。",
       "kana": "ゆきのため、れっしゃがおくれた。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "ゆき",
           "unlifted": "雪"
@@ -715,6 +744,10 @@
           "lifted": null,
           "unlifted": "ため"
         },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
         {
           "lifted": "れっしゃ",
           "unlifted": "列車"
@@ -734,6 +767,10 @@
       "kanji": "雪のせいで私は電車に乗り遅れた。",
       "kana": "ゆきのせいでわたしはでんしゃにのりおくれた。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "ゆき",
           "unlifted": "雪"
@@ -769,6 +806,10 @@
       "kanji": "切符なしで電車に乗ってはいけません。",
       "kana": "きっぷなしででんしゃにのってはいけません。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "きっぷ",
           "unlifted": "切符"
@@ -804,6 +845,10 @@
       "kanji": "積み荷が落ちたので、トラックは停車しなければならなかった。",
       "kana": "つみにがおちたので、トラックはていしゃしなければならなかった。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "つみに",
           "unlifted": "積み荷"
@@ -820,6 +865,10 @@
           "lifted": null,
           "unlifted": "ので"
         },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
         {
           "lifted": null,
           "unlifted": "トラック"
@@ -841,6 +890,49 @@
           "unlifted": "なければならなかった"
         }
       ]
+    },
+    {
+      "english": "I'll come at noon to pick you up.",
+      "kanji": "正午に車で迎えに行くよ。",
+      "kana": "しょうごにくるまでむかえにいくよ。",
+      "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
+        {
+          "lifted": "しょうご",
+          "unlifted": "正午"
+        },
+        {
+          "lifted": null,
+          "unlifted": "に"
+        },
+        {
+          "lifted": "くるま",
+          "unlifted": "車"
+        },
+        {
+          "lifted": null,
+          "unlifted": "で"
+        },
+        {
+          "lifted": "むか",
+          "unlifted": "迎え"
+        },
+        {
+          "lifted": null,
+          "unlifted": "に"
+        },
+        {
+          "lifted": "い",
+          "unlifted": "行く"
+        },
+        {
+          "lifted": null,
+          "unlifted": "よ"
+        }
+      ]
     }
   ],
   "uri": "https://jisho.org/search/%E8%BB%8A%23sentences"
diff --git a/test/example_test_cases/1.json b/test/example_test_cases/1.json
index 9100cff..d92f543 100644
--- a/test/example_test_cases/1.json
+++ b/test/example_test_cases/1.json
@@ -7,10 +7,18 @@
       "kanji": "戦後、日本人の勤勉さと節約はアメリカ人に強い印象を与えた。",
       "kana": "せんご、にほんじんのきんべんさとせつやくはアメリカじんにつよいいんしょうをあたえた。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "せんご",
           "unlifted": "戦後"
         },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
         {
           "lifted": "にほんじん",
           "unlifted": "日本人"
@@ -58,6 +66,10 @@
       "kanji": "清潔は日本人の習性だ。",
       "kana": "せいけつはにほんじんのしゅうせいだ。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "せいけつ",
           "unlifted": "清潔"
@@ -89,6 +101,10 @@
       "kanji": "乗船客は主に日本人だった。",
       "kana": "じょうせんきゃくはおもににほんじんだった。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "じょうせん",
           "unlifted": "乗船"
@@ -120,6 +136,10 @@
       "kanji": "出席をしている人々は全部日本人です。",
       "kana": "しゅっせきをしているひとびと々はぜんぶにほんじんです。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "しゅっせき",
           "unlifted": "出席"
@@ -159,6 +179,10 @@
       "kanji": "若い日本人の中には、結婚するより独身でいることを好む者もいる。",
       "kana": "わかいにほんじんのなかには、けっこんするよりどくしんでいることをこのむものもいる。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "わか",
           "unlifted": "若い"
@@ -179,6 +203,10 @@
           "lifted": null,
           "unlifted": "には"
         },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
         {
           "lifted": "けっこん",
           "unlifted": "結婚する"
@@ -230,6 +258,10 @@
       "kanji": "私は彼が日本人だとは知らなかった。",
       "kana": "わたしはかれがにほんじんだとはしらなかった。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "わたし",
           "unlifted": "私"
@@ -273,6 +305,10 @@
       "kanji": "私は日本人一般について言っているのだ。",
       "kana": "わたしはにほんじんいっぱんについていっているのだ。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "わたし",
           "unlifted": "私"
@@ -308,6 +344,10 @@
       "kanji": "私は日本人ですが、あなたはアメリカ人です。",
       "kana": "わたしはにほんじんですが、あなたはアメリカじんです。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "わたし",
           "unlifted": "私"
@@ -328,6 +368,10 @@
           "lifted": null,
           "unlifted": "が"
         },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
         {
           "lifted": null,
           "unlifted": "あなた"
@@ -351,6 +395,10 @@
       "kanji": "私は仕事中毒者は日本人だけかと思っていました。",
       "kana": "わたしはしごとちゅうどくしゃはにほんじんだけかとおもっていました。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "わたし",
           "unlifted": "私"
@@ -402,6 +450,10 @@
       "kanji": "日本人ならそんなことはけっしてしないでしょう。",
       "kana": "にほんじんならそんなことはけっしてしないでしょう。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "にほんじん",
           "unlifted": "日本人"
@@ -441,6 +493,10 @@
       "kanji": "こんな歌を残している明治天皇の一面を知っている日本人は少ないのではないだろうか。",
       "kana": "こんなうたをのこしているめいじてんのうのいちめんをしっているにほんじんはすくないのではないだろうか。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": null,
           "unlifted": "こんな"
@@ -508,6 +564,10 @@
       "kanji": "私は日本人ですが、日本に住んでいません。",
       "kana": "わたしはにほんじんですが、にほんにすんでいません。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "わたし",
           "unlifted": "私"
@@ -528,6 +588,10 @@
           "lifted": null,
           "unlifted": "が"
         },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
         {
           "lifted": "にほん",
           "unlifted": "日本"
@@ -547,6 +611,10 @@
       "kanji": "向こうではセレブという言葉を「金持ち」の意味では使わない。という事で日本人と判明しました。",
       "kana": "むこうではセレブということばを「かねもち」のいみではつかわない。ということでにほんじんとはんめいしました。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "む",
           "unlifted": "向こう"
@@ -575,10 +643,18 @@
           "lifted": null,
           "unlifted": "を"
         },
+        {
+          "lifted": null,
+          "unlifted": "「"
+        },
         {
           "lifted": "かねも",
           "unlifted": "金持ち"
         },
+        {
+          "lifted": null,
+          "unlifted": "」"
+        },
         {
           "lifted": null,
           "unlifted": "の"
@@ -599,6 +675,10 @@
           "lifted": "つか",
           "unlifted": "使わない"
         },
+        {
+          "lifted": null,
+          "unlifted": "。"
+        },
         {
           "lifted": null,
           "unlifted": "と"
@@ -638,6 +718,10 @@
       "kanji": "日本人で英語をうまく使える人はほとんどいません。",
       "kana": "にほんじんでえいごをうまくつかえるひとはほとんどいません。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "にほんじん",
           "unlifted": "日本人"
@@ -685,6 +769,10 @@
       "kanji": "日本人離れしたこの美しい相貌からもわかるように、優奈は実は生粋の日本人じゃない。西洋人をおばあちゃんに持つ、クォーターだったりする。",
       "kana": "にほんじんはなれしたこのうつくしいそうぼうからもわかるように、優奈はじつはきっすいのにほんじんじゃない。せいようじんをおばあちゃんにもつ、クォーターだったりする。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "にほんじん",
           "unlifted": "日本人"
@@ -725,6 +813,10 @@
           "lifted": null,
           "unlifted": "ように"
         },
+        {
+          "lifted": null,
+          "unlifted": "、優奈"
+        },
         {
           "lifted": null,
           "unlifted": "は"
@@ -745,6 +837,10 @@
           "lifted": null,
           "unlifted": "じゃない"
         },
+        {
+          "lifted": null,
+          "unlifted": "。"
+        },
         {
           "lifted": "せいようじん",
           "unlifted": "西洋人"
@@ -765,6 +861,10 @@
           "lifted": "も",
           "unlifted": "持つ"
         },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
         {
           "lifted": null,
           "unlifted": "クォーター"
@@ -784,6 +884,10 @@
       "kanji": "今日のトピックは「北朝鮮による日本人拉致問題」です。",
       "kana": "きょうのトピックは「きたちょうせんによるにほんじんらちもんだい」です。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "きょう",
           "unlifted": "今日"
@@ -800,6 +904,10 @@
           "lifted": null,
           "unlifted": "は"
         },
+        {
+          "lifted": null,
+          "unlifted": "「"
+        },
         {
           "lifted": "きたちょうせん",
           "unlifted": "北朝鮮"
@@ -820,6 +928,10 @@
           "lifted": "もんだい",
           "unlifted": "問題"
         },
+        {
+          "lifted": null,
+          "unlifted": "」"
+        },
         {
           "lifted": null,
           "unlifted": "です"
@@ -831,6 +943,10 @@
       "kanji": "外米はぼそぼそしていて、日本人の口には合わない。",
       "kana": "がいまいはぼそぼそしていて、にほんじんのくちにはあわない。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "がいまい",
           "unlifted": "外米"
@@ -847,6 +963,10 @@
           "lifted": null,
           "unlifted": "していて"
         },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
         {
           "lifted": "にほんじん",
           "unlifted": "日本人"
@@ -874,10 +994,18 @@
       "kanji": "毎年、多くの日本人が海外へ旅行する。",
       "kana": "まいとし、おおくのにほんじんがかいがいへりょこうする。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "まいとし",
           "unlifted": "毎年"
         },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
         {
           "lifted": "おお",
           "unlifted": "多く"
@@ -917,6 +1045,10 @@
       "kanji": "彼女の父親は日本人だ。",
       "kana": "かのじょのちちおやはにほんじんだ。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "かのじょ",
           "unlifted": "彼女の"
@@ -944,6 +1076,10 @@
       "kanji": "彼らは日本人労働者が不足しているから外国人を雇う。",
       "kana": "かれらはにほんじんろうどうしゃがふそくしているからがいこくじんをやとう。",
       "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
         {
           "lifted": "かれ",
           "unlifted": "彼ら"
diff --git a/test/example_test_cases/3.json b/test/example_test_cases/3.json
index 2aeacd4..09c2058 100644
--- a/test/example_test_cases/3.json
+++ b/test/example_test_cases/3.json
@@ -3,37 +3,190 @@
   "found": true,
   "results": [
     {
-      "english": "All the villagers in turn saluted the priest.",
-      "kanji": "村人はみなかわるがわる僧にあいさつした。",
-      "kana": "むらびとはみなかわるがわるそうにあいさつした。",
+      "english": "The total solar eclipse can be observed next year on June 22nd.",
+      "kanji": "来年6月22日に観測される皆既日食。",
+      "kana": "らいねん6月22にちにかんそくされるかいきにっしょく。",
       "pieces": [
         {
-          "lifted": "むらびと",
-          "unlifted": "村人"
+          "lifted": null,
+          "unlifted": "\n      "
+        },
+        {
+          "lifted": "らいねん",
+          "unlifted": "来年"
+        },
+        {
+          "lifted": null,
+          "unlifted": "6月"
+        },
+        {
+          "lifted": null,
+          "unlifted": "22"
+        },
+        {
+          "lifted": "にち",
+          "unlifted": "日"
+        },
+        {
+          "lifted": null,
+          "unlifted": "に"
+        },
+        {
+          "lifted": "かんそく",
+          "unlifted": "観測"
+        },
+        {
+          "lifted": null,
+          "unlifted": "される"
+        },
+        {
+          "lifted": "かいきにっしょく",
+          "unlifted": "皆既日食"
+        }
+      ]
+    },
+    {
+      "english": "Do you all place great importance on morals?",
+      "kanji": "皆さんは、モラルを大切にしていますか。",
+      "kana": "みなさんは、モラルをたいせつにしていますか。",
+      "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
+        {
+          "lifted": "みな",
+          "unlifted": "皆さん"
         },
         {
           "lifted": null,
           "unlifted": "は"
         },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
+        {
+          "lifted": null,
+          "unlifted": "モラル"
+        },
+        {
+          "lifted": null,
+          "unlifted": "を"
+        },
+        {
+          "lifted": "たいせつ",
+          "unlifted": "大切に"
+        },
+        {
+          "lifted": null,
+          "unlifted": "しています"
+        },
+        {
+          "lifted": null,
+          "unlifted": "か"
+        }
+      ]
+    },
+    {
+      "english": "Will everyone please stick with it to the last moment.",
+      "kanji": "どうぞ、皆様も最後の一瞬まで粘り抜いてください。",
+      "kana": "どうぞ、みなさまもさいごのいっしゅんまでねばりぬいてください。",
+      "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
+        {
+          "lifted": null,
+          "unlifted": "どうぞ"
+        },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
+        {
+          "lifted": "みなさま",
+          "unlifted": "皆様"
+        },
+        {
+          "lifted": null,
+          "unlifted": "も"
+        },
+        {
+          "lifted": "さいご",
+          "unlifted": "最後"
+        },
+        {
+          "lifted": null,
+          "unlifted": "の"
+        },
+        {
+          "lifted": "いっしゅん",
+          "unlifted": "一瞬"
+        },
+        {
+          "lifted": null,
+          "unlifted": "まで"
+        },
+        {
+          "lifted": "ねばりぬ",
+          "unlifted": "粘り抜いて"
+        },
+        {
+          "lifted": null,
+          "unlifted": "ください"
+        }
+      ]
+    },
+    {
+      "english": "We were all pleased to be so cheaply quit of him.",
+      "kanji": "これだけで厄介払いできたら安いもので、みな大喜びした。",
+      "kana": "これだけでやっかいばらいできたらやすいもので、みなおおよろこびした。",
+      "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
+        {
+          "lifted": null,
+          "unlifted": "これだけ"
+        },
+        {
+          "lifted": null,
+          "unlifted": "で"
+        },
+        {
+          "lifted": "やっかいばら",
+          "unlifted": "厄介払い"
+        },
+        {
+          "lifted": null,
+          "unlifted": "できたら"
+        },
+        {
+          "lifted": "やす",
+          "unlifted": "安い"
+        },
+        {
+          "lifted": null,
+          "unlifted": "もの"
+        },
+        {
+          "lifted": null,
+          "unlifted": "で"
+        },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
         {
           "lifted": null,
           "unlifted": "みな"
         },
         {
-          "lifted": null,
-          "unlifted": "かわるがわる"
-        },
-        {
-          "lifted": "そう",
-          "unlifted": "僧"
-        },
-        {
-          "lifted": null,
-          "unlifted": "に"
-        },
-        {
-          "lifted": null,
-          "unlifted": "あいさつ"
+          "lifted": "おおよろこ",
+          "unlifted": "大喜び"
         },
         {
           "lifted": null,
@@ -42,148 +195,283 @@
       ]
     },
     {
-      "english": "All the villagers went out into the hills to look for a missing cat.",
-      "kanji": "村人たちは皆、行方不明になった猫を探すために山の中へでかけた。",
-      "kana": "むらびとたちはみんな、ゆくえふめいになったねこをさがすためにやまのなかへでかけた。",
+      "english": "For my part, having you lot with me is more reassuring than the police or anything!",
+      "kanji": "僕には警察よりも何よりもみんながいてくれることの方が心強いのですよ。",
+      "kana": "ぼくにはけいさつよりもなによりもみんながいてくれることのほうがこころづよいのですよ。",
       "pieces": [
         {
-          "lifted": "むらびと",
-          "unlifted": "村人"
+          "lifted": null,
+          "unlifted": "\n      "
+        },
+        {
+          "lifted": "ぼく",
+          "unlifted": "僕"
         },
         {
           "lifted": null,
-          "unlifted": "たち"
+          "unlifted": "には"
+        },
+        {
+          "lifted": "けいさつ",
+          "unlifted": "警察"
         },
         {
           "lifted": null,
-          "unlifted": "は"
+          "unlifted": "よりも"
         },
         {
-          "lifted": "みんな",
-          "unlifted": "皆"
-        },
-        {
-          "lifted": "ゆくえふめい",
-          "unlifted": "行方不明"
+          "lifted": "なに",
+          "unlifted": "何"
         },
         {
           "lifted": null,
-          "unlifted": "になった"
-        },
-        {
-          "lifted": "ねこ",
-          "unlifted": "猫"
+          "unlifted": "よりも"
         },
         {
           "lifted": null,
-          "unlifted": "を"
-        },
-        {
-          "lifted": "さが",
-          "unlifted": "探す"
+          "unlifted": "みんな"
         },
         {
           "lifted": null,
-          "unlifted": "ために"
-        },
-        {
-          "lifted": "やま",
-          "unlifted": "山"
+          "unlifted": "が"
         },
         {
           "lifted": null,
-          "unlifted": "の"
-        },
-        {
-          "lifted": "なか",
-          "unlifted": "中"
+          "unlifted": "いて"
         },
         {
           "lifted": null,
-          "unlifted": "へ"
-        },
-        {
-          "lifted": null,
-          "unlifted": "でかけた"
-        }
-      ]
-    },
-    {
-      "english": "The festival is looked forward to by the villagers.",
-      "kanji": "村人たちはみな祭りを楽しみにしている。",
-      "kana": "むらびとたちはみなまつりをたのしみにしている。",
-      "pieces": [
-        {
-          "lifted": "むらびと",
-          "unlifted": "村人"
-        },
-        {
-          "lifted": null,
-          "unlifted": "たち"
-        },
-        {
-          "lifted": null,
-          "unlifted": "は"
-        },
-        {
-          "lifted": null,
-          "unlifted": "みな"
-        },
-        {
-          "lifted": "まつ",
-          "unlifted": "祭り"
-        },
-        {
-          "lifted": null,
-          "unlifted": "を"
-        },
-        {
-          "lifted": "たの",
-          "unlifted": "楽しみにしている"
-        }
-      ]
-    },
-    {
-      "english": "All the villagers know of the accident.",
-      "kanji": "村の人々は皆その事故のことを知っている。",
-      "kana": "むらのひとびと々はみんなそのじこのことをしっている。",
-      "pieces": [
-        {
-          "lifted": "むら",
-          "unlifted": "村"
-        },
-        {
-          "lifted": null,
-          "unlifted": "の"
-        },
-        {
-          "lifted": "ひとびと",
-          "unlifted": "人々"
-        },
-        {
-          "lifted": null,
-          "unlifted": "は"
-        },
-        {
-          "lifted": "みんな",
-          "unlifted": "皆"
-        },
-        {
-          "lifted": null,
-          "unlifted": "その"
-        },
-        {
-          "lifted": "じこ",
-          "unlifted": "事故"
-        },
-        {
-          "lifted": null,
-          "unlifted": "の"
+          "unlifted": "くれる"
         },
         {
           "lifted": null,
           "unlifted": "こと"
         },
+        {
+          "lifted": null,
+          "unlifted": "の"
+        },
+        {
+          "lifted": "ほう",
+          "unlifted": "方"
+        },
+        {
+          "lifted": null,
+          "unlifted": "が"
+        },
+        {
+          "lifted": "こころづよ",
+          "unlifted": "心強い"
+        },
+        {
+          "lifted": null,
+          "unlifted": "のです"
+        },
+        {
+          "lifted": null,
+          "unlifted": "よ"
+        }
+      ]
+    },
+    {
+      "english": "What programming language does everybody like?",
+      "kanji": "皆さんはどんなプログラミング言語が好きですか?",
+      "kana": "みなさんはどんなプログラミングげんごがすきですか?",
+      "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
+        {
+          "lifted": "みな",
+          "unlifted": "皆さん"
+        },
+        {
+          "lifted": null,
+          "unlifted": "は"
+        },
+        {
+          "lifted": null,
+          "unlifted": "どんな"
+        },
+        {
+          "lifted": "プログラミングげんご",
+          "unlifted": "プログラミング言語"
+        },
+        {
+          "lifted": null,
+          "unlifted": "が"
+        },
+        {
+          "lifted": "す",
+          "unlifted": "好き"
+        },
+        {
+          "lifted": null,
+          "unlifted": "ですか"
+        }
+      ]
+    },
+    {
+      "english": "I'm teaching basic participial constructions now, but, with regard to those below, what different ways of translating them would everybody use?",
+      "kanji": "今、基本的な分詞構文を教えているのですが、皆さんは以下の分詞構文の訳については、どのように異なる訳し方をされますか?",
+      "kana": "いま、きほんてきなぶんしこうぶんをおしええているのですが、みなさんはいかのぶんしこうぶんのやくについては、どのようにことなるやくしかたをされますか?",
+      "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
+        {
+          "lifted": "いま",
+          "unlifted": "今"
+        },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
+        {
+          "lifted": "きほんてき",
+          "unlifted": "基本的な"
+        },
+        {
+          "lifted": "ぶんしこうぶん",
+          "unlifted": "分詞構文"
+        },
+        {
+          "lifted": null,
+          "unlifted": "を"
+        },
+        {
+          "lifted": "おしえ",
+          "unlifted": "教えている"
+        },
+        {
+          "lifted": null,
+          "unlifted": "のです"
+        },
+        {
+          "lifted": null,
+          "unlifted": "が"
+        },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
+        {
+          "lifted": "みな",
+          "unlifted": "皆さん"
+        },
+        {
+          "lifted": null,
+          "unlifted": "は"
+        },
+        {
+          "lifted": "いか",
+          "unlifted": "以下"
+        },
+        {
+          "lifted": null,
+          "unlifted": "の"
+        },
+        {
+          "lifted": "ぶんしこうぶん",
+          "unlifted": "分詞構文"
+        },
+        {
+          "lifted": null,
+          "unlifted": "の"
+        },
+        {
+          "lifted": "やく",
+          "unlifted": "訳"
+        },
+        {
+          "lifted": null,
+          "unlifted": "について"
+        },
+        {
+          "lifted": null,
+          "unlifted": "は"
+        },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
+        {
+          "lifted": null,
+          "unlifted": "どのように"
+        },
+        {
+          "lifted": "こと",
+          "unlifted": "異なる"
+        },
+        {
+          "lifted": "やく",
+          "unlifted": "訳し"
+        },
+        {
+          "lifted": "かた",
+          "unlifted": "方"
+        },
+        {
+          "lifted": null,
+          "unlifted": "を"
+        },
+        {
+          "lifted": null,
+          "unlifted": "されます"
+        },
+        {
+          "lifted": null,
+          "unlifted": "か"
+        }
+      ]
+    },
+    {
+      "english": "What's different from Japan is that the doctors of Singapore generally all know each other.",
+      "kanji": "シンガポールの医師は殆どの場合皆お互いを知っている、というのが日本と異なります。",
+      "kana": "シンガポールのいしはほとんどのばあいみんなおたがいをしっている、というのがにほんとことなります。",
+      "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
+        {
+          "lifted": null,
+          "unlifted": "シンガポール"
+        },
+        {
+          "lifted": null,
+          "unlifted": "の"
+        },
+        {
+          "lifted": "いし",
+          "unlifted": "医師"
+        },
+        {
+          "lifted": null,
+          "unlifted": "は"
+        },
+        {
+          "lifted": "ほとん",
+          "unlifted": "殆ど"
+        },
+        {
+          "lifted": null,
+          "unlifted": "の"
+        },
+        {
+          "lifted": "ばあい",
+          "unlifted": "場合"
+        },
+        {
+          "lifted": "みんな",
+          "unlifted": "皆"
+        },
+        {
+          "lifted": "おたが",
+          "unlifted": "お互い"
+        },
         {
           "lifted": null,
           "unlifted": "を"
@@ -191,25 +479,57 @@
         {
           "lifted": "し",
           "unlifted": "知っている"
-        }
-      ]
-    },
-    {
-      "english": "Everybody in the village looks up to him.",
-      "kanji": "村の人はみな彼のことを尊敬している。",
-      "kana": "むらのひとはみなかれのことをそんけいしている。",
-      "pieces": [
+        },
         {
-          "lifted": "むら",
-          "unlifted": "村"
+          "lifted": null,
+          "unlifted": "、"
+        },
+        {
+          "lifted": null,
+          "unlifted": "と"
+        },
+        {
+          "lifted": null,
+          "unlifted": "いう"
         },
         {
           "lifted": null,
           "unlifted": "の"
         },
         {
-          "lifted": "ひと",
-          "unlifted": "人"
+          "lifted": null,
+          "unlifted": "が"
+        },
+        {
+          "lifted": "にほん",
+          "unlifted": "日本"
+        },
+        {
+          "lifted": null,
+          "unlifted": "と"
+        },
+        {
+          "lifted": "こと",
+          "unlifted": "異なります"
+        }
+      ]
+    },
+    {
+      "english": "Everyone, please keep to netiquette.",
+      "kanji": "皆さんネチケットはしっかり。",
+      "kana": "みなさんネチケットはしっかり。",
+      "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
+        {
+          "lifted": "みな",
+          "unlifted": "皆さん"
+        },
+        {
+          "lifted": null,
+          "unlifted": "ネチケット"
         },
         {
           "lifted": null,
@@ -217,276 +537,267 @@
         },
         {
           "lifted": null,
-          "unlifted": "みな"
+          "unlifted": "しっかり"
+        }
+      ]
+    },
+    {
+      "english": "The example is a past progressive tense sentence. How was everybody taught when they were learning about progressive tense?",
+      "kanji": "例文は過去進行形の文です。皆さんは進行形を学習するとき、どのように教わりましたか?",
+      "kana": "れいぶんはかこしんこうけいのぶんです。みなさんはしんこうけいをがくしゅうするとき、どのようにおそわりましたか?",
+      "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
         },
         {
-          "lifted": "かれ",
-          "unlifted": "彼"
+          "lifted": "れいぶん",
+          "unlifted": "例文"
+        },
+        {
+          "lifted": null,
+          "unlifted": "は"
+        },
+        {
+          "lifted": "かこしんこうけい",
+          "unlifted": "過去進行形"
         },
         {
           "lifted": null,
           "unlifted": "の"
         },
+        {
+          "lifted": "ぶん",
+          "unlifted": "文"
+        },
         {
           "lifted": null,
-          "unlifted": "こと"
+          "unlifted": "です"
+        },
+        {
+          "lifted": null,
+          "unlifted": "。"
+        },
+        {
+          "lifted": "みな",
+          "unlifted": "皆さん"
+        },
+        {
+          "lifted": null,
+          "unlifted": "は"
+        },
+        {
+          "lifted": "しんこうけい",
+          "unlifted": "進行形"
         },
         {
           "lifted": null,
           "unlifted": "を"
         },
         {
-          "lifted": "そんけい",
-          "unlifted": "尊敬"
+          "lifted": "がくしゅう",
+          "unlifted": "学習"
         },
         {
           "lifted": null,
-          "unlifted": "している"
+          "unlifted": "する"
+        },
+        {
+          "lifted": null,
+          "unlifted": "とき"
+        },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
+        {
+          "lifted": null,
+          "unlifted": "どのように"
+        },
+        {
+          "lifted": "おそ",
+          "unlifted": "教わりました"
+        },
+        {
+          "lifted": null,
+          "unlifted": "か"
         }
       ]
     },
     {
-      "english": "The frost killed all the flowers.",
-      "kanji": "霜で花はみんな枯れた。",
-      "kana": "しもではなはみんなかれた。",
+      "english": "Oh, that's a secret, OK? Because slipping out of the dorm in the night is severely punished.",
+      "kanji": "あ、みんなには内緒だよ?寮を夜中に抜け出すのは厳罰だからね?",
+      "kana": "あ、みんなにはないしょだよ?りょうをよなかにぬけだすのはげんばつだからね?",
       "pieces": [
         {
-          "lifted": "しも",
-          "unlifted": "霜"
+          "lifted": null,
+          "unlifted": "\n      "
         },
         {
           "lifted": null,
-          "unlifted": "で"
-        },
-        {
-          "lifted": "はな",
-          "unlifted": "花"
+          "unlifted": "あ"
         },
         {
           "lifted": null,
-          "unlifted": "は"
+          "unlifted": "、"
         },
         {
           "lifted": null,
           "unlifted": "みんな"
         },
         {
-          "lifted": "か",
-          "unlifted": "枯れた"
-        }
-      ]
-    },
-    {
-      "english": "All the early flowers were bitten by the frost.",
-      "kanji": "早咲きの花はみんな霜にやられた。",
-      "kana": "はやざきのはなはみんなしもにやられた。",
-      "pieces": [
+          "lifted": null,
+          "unlifted": "には"
+        },
         {
-          "lifted": "はやざ",
-          "unlifted": "早咲き"
+          "lifted": "ないしょ",
+          "unlifted": "内緒"
+        },
+        {
+          "lifted": null,
+          "unlifted": "だ"
+        },
+        {
+          "lifted": null,
+          "unlifted": "よ"
+        },
+        {
+          "lifted": null,
+          "unlifted": "?"
+        },
+        {
+          "lifted": "りょう",
+          "unlifted": "寮"
+        },
+        {
+          "lifted": null,
+          "unlifted": "を"
+        },
+        {
+          "lifted": "よなか",
+          "unlifted": "夜中"
+        },
+        {
+          "lifted": null,
+          "unlifted": "に"
+        },
+        {
+          "lifted": "ぬけだ",
+          "unlifted": "抜け出す"
         },
         {
           "lifted": null,
           "unlifted": "の"
         },
-        {
-          "lifted": "はな",
-          "unlifted": "花"
-        },
         {
           "lifted": null,
           "unlifted": "は"
         },
         {
-          "lifted": null,
-          "unlifted": "みんな"
-        },
-        {
-          "lifted": "しも",
-          "unlifted": "霜"
+          "lifted": "げんばつ",
+          "unlifted": "厳罰"
         },
         {
           "lifted": null,
-          "unlifted": "に"
+          "unlifted": "だ"
         },
         {
           "lifted": null,
-          "unlifted": "やられた"
+          "unlifted": "から"
+        },
+        {
+          "lifted": null,
+          "unlifted": "ね"
         }
       ]
     },
     {
-      "english": "All students have access to the library.",
-      "kanji": "全学生はみんな図書館に入ることができる。",
-      "kana": "ぜんがくせいはみんなとしょかんにはいることができる。",
+      "english": "\"I've heard about it, Koichi\" \"You don't need to say anything more, I know. It's the summer festival incident at the shrine, right?\"",
+      "kanji": "「聞いたよ、光一」「まあ皆までいうなって。分かってる。神社の夏祭りの一件でしょ?」",
+      "kana": "「きいたよ、光一」「まあ皆までいうなって。わかかってる。じんじゃのなつまつりのいっけんでしょ?」",
       "pieces": [
         {
-          "lifted": "ぜん",
-          "unlifted": "全"
+          "lifted": null,
+          "unlifted": "\n      「"
         },
         {
-          "lifted": "がくせい",
-          "unlifted": "学生"
+          "lifted": "き",
+          "unlifted": "聞いた"
         },
         {
           "lifted": null,
-          "unlifted": "は"
+          "unlifted": "よ"
         },
         {
           "lifted": null,
-          "unlifted": "みんな"
-        },
-        {
-          "lifted": "としょかん",
-          "unlifted": "図書館"
+          "unlifted": "、光一」「"
         },
         {
           "lifted": null,
-          "unlifted": "に"
-        },
-        {
-          "lifted": "はい",
-          "unlifted": "入る"
+          "unlifted": "まあ"
         },
         {
           "lifted": null,
-          "unlifted": "ことができる"
-        }
-      ]
-    },
-    {
-      "english": "All the players were in position.",
-      "kanji": "選手達はみな位置についていた。",
-      "kana": "せんしゅたちはみないちについていた。",
-      "pieces": [
-        {
-          "lifted": "せんしゅ",
-          "unlifted": "選手"
-        },
-        {
-          "lifted": "たち",
-          "unlifted": "達"
+          "unlifted": "皆までいうな"
         },
         {
           "lifted": null,
-          "unlifted": "は"
+          "unlifted": "って"
         },
         {
           "lifted": null,
-          "unlifted": "みな"
+          "unlifted": "。"
         },
         {
-          "lifted": "いち",
-          "unlifted": "位置"
+          "lifted": "わか",
+          "unlifted": "分かってる"
         },
         {
           "lifted": null,
-          "unlifted": "に"
+          "unlifted": "。"
         },
         {
-          "lifted": null,
-          "unlifted": "ついていた"
-        }
-      ]
-    },
-    {
-      "english": "All the players did their best.",
-      "kanji": "選手たちみんなが最善をつくした。",
-      "kana": "せんしゅたちみんながさいぜんをつをつくした。",
-      "pieces": [
-        {
-          "lifted": "せんしゅ",
-          "unlifted": "選手"
-        },
-        {
-          "lifted": null,
-          "unlifted": "たち"
-        },
-        {
-          "lifted": null,
-          "unlifted": "みんな"
-        },
-        {
-          "lifted": null,
-          "unlifted": "が"
-        },
-        {
-          "lifted": "さいぜんをつ",
-          "unlifted": "最善をつくした"
-        }
-      ]
-    },
-    {
-      "english": "Everyone was glued to the TV set as the election results came in.",
-      "kanji": "選挙の結果出てくるにつれ、皆テレビにかじりついた。",
-      "kana": "せんきょのけっかでてくるにつれ、みんなテレビにかじりついた。",
-      "pieces": [
-        {
-          "lifted": "せんきょ",
-          "unlifted": "選挙"
+          "lifted": "じんじゃ",
+          "unlifted": "神社"
         },
         {
           "lifted": null,
           "unlifted": "の"
         },
         {
-          "lifted": "けっか",
-          "unlifted": "結果"
-        },
-        {
-          "lifted": "で",
-          "unlifted": "出てくる"
-        },
-        {
-          "lifted": null,
-          "unlifted": "につれ"
-        },
-        {
-          "lifted": "みんな",
-          "unlifted": "皆"
-        },
-        {
-          "lifted": null,
-          "unlifted": "テレビ"
-        },
-        {
-          "lifted": null,
-          "unlifted": "に"
-        },
-        {
-          "lifted": null,
-          "unlifted": "かじりついた"
-        }
-      ]
-    },
-    {
-      "english": "I may not have much to offer in the way of learning or ability, but I want to do whatever I can for us all and humbly ask for your favor.",
-      "kanji": "浅学非才の私ではありますが、何とぞ皆様のお力を賜りたく、ここにお願い申し上げる次第です。",
-      "kana": "せんがくひさいのわたしではありますが、なにとぞみなさまのおちからをたまわりたく、ここにおねがいもうしあげるしだいです。",
-      "pieces": [
-        {
-          "lifted": "せんがくひさい",
-          "unlifted": "浅学非才"
+          "lifted": "なつまつ",
+          "unlifted": "夏祭り"
         },
         {
           "lifted": null,
           "unlifted": "の"
         },
         {
-          "lifted": "わたし",
-          "unlifted": "私"
+          "lifted": "いっけん",
+          "unlifted": "一件"
         },
         {
           "lifted": null,
-          "unlifted": "ではあります"
+          "unlifted": "でしょ"
+        }
+      ]
+    },
+    {
+      "english": "We plan to elicit opinions from the public.",
+      "kanji": "市民の皆様の御意見をちょうだいする予定です。",
+      "kana": "しみんのみなさまのごいけんをちょうだいするよていです。",
+      "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
+        {
+          "lifted": "しみん",
+          "unlifted": "市民"
         },
         {
           "lifted": null,
-          "unlifted": "が"
-        },
-        {
-          "lifted": "なに",
-          "unlifted": "何とぞ"
+          "unlifted": "の"
         },
         {
           "lifted": "みなさま",
@@ -497,40 +808,28 @@
           "unlifted": "の"
         },
         {
-          "lifted": null,
-          "unlifted": "お"
+          "lifted": "ご",
+          "unlifted": "御"
         },
         {
-          "lifted": "ちから",
-          "unlifted": "力"
+          "lifted": "いけん",
+          "unlifted": "意見"
         },
         {
           "lifted": null,
           "unlifted": "を"
         },
         {
-          "lifted": "たまわ",
-          "unlifted": "賜り"
+          "lifted": null,
+          "unlifted": "ちょうだい"
         },
         {
           "lifted": null,
-          "unlifted": "たく"
+          "unlifted": "する"
         },
         {
-          "lifted": null,
-          "unlifted": "ここ"
-        },
-        {
-          "lifted": null,
-          "unlifted": "に"
-        },
-        {
-          "lifted": "おねがいもうしあ",
-          "unlifted": "お願い申し上げる"
-        },
-        {
-          "lifted": "しだい",
-          "unlifted": "次第"
+          "lifted": "よてい",
+          "unlifted": "予定"
         },
         {
           "lifted": null,
@@ -539,217 +838,266 @@
       ]
     },
     {
-      "english": "War doesn't make anybody happy.",
-      "kanji": "戦争はみんなを不幸せにする。",
-      "kana": "せんそうはみんなをふしあわせにする。",
+      "english": "Having scattered the enemy before me and triumphantly returned, this is how they would herald me.",
+      "kanji": "敵を蹴散らし、凱旋した俺はみなにこう呼ばれるんだ!",
+      "kana": "てきをけちらし、がいせんしたおれはみなにこうよばれるんだ!",
       "pieces": [
         {
-          "lifted": "せんそう",
-          "unlifted": "戦争"
+          "lifted": null,
+          "unlifted": "\n      "
         },
         {
-          "lifted": null,
-          "unlifted": "は"
-        },
-        {
-          "lifted": null,
-          "unlifted": "みんな"
+          "lifted": "てき",
+          "unlifted": "敵"
         },
         {
           "lifted": null,
           "unlifted": "を"
         },
         {
-          "lifted": "ふしあわ",
-          "unlifted": "不幸せ"
+          "lifted": "けち",
+          "unlifted": "蹴散らし"
         },
         {
           "lifted": null,
-          "unlifted": "に"
+          "unlifted": "、"
+        },
+        {
+          "lifted": "がいせん",
+          "unlifted": "凱旋"
         },
         {
           "lifted": null,
-          "unlifted": "する"
-        }
-      ]
-    },
-    {
-      "english": "The other day I attended a class reunion of my elementary school.",
-      "kanji": "先日小学校のクラス会に出席した。",
-      "kana": "せんじつしょうがっこうのクラスかいにしゅっせきした。",
-      "pieces": [
-        {
-          "lifted": "せんじつ",
-          "unlifted": "先日"
+          "unlifted": "した"
         },
         {
-          "lifted": "しょうがっこう",
-          "unlifted": "小学校"
-        },
-        {
-          "lifted": null,
-          "unlifted": "の"
-        },
-        {
-          "lifted": "クラスかい",
-          "unlifted": "クラス会"
-        },
-        {
-          "lifted": null,
-          "unlifted": "に"
-        },
-        {
-          "lifted": "しゅっせき",
-          "unlifted": "出席した"
-        }
-      ]
-    },
-    {
-      "english": "The teacher called each student by name.",
-      "kanji": "先生は生徒みんなを名前で呼んだ。",
-      "kana": "せんせいはせいとみんなをなまえでよんだ。",
-      "pieces": [
-        {
-          "lifted": "せんせい",
-          "unlifted": "先生"
+          "lifted": "おれ",
+          "unlifted": "俺"
         },
         {
           "lifted": null,
           "unlifted": "は"
         },
-        {
-          "lifted": "せいと",
-          "unlifted": "生徒"
-        },
-        {
-          "lifted": null,
-          "unlifted": "みんな"
-        },
-        {
-          "lifted": null,
-          "unlifted": "を"
-        },
-        {
-          "lifted": "なまえ",
-          "unlifted": "名前"
-        },
-        {
-          "lifted": null,
-          "unlifted": "で"
-        },
-        {
-          "lifted": "よ",
-          "unlifted": "呼んだ"
-        }
-      ]
-    },
-    {
-      "english": "The teacher asked me if I was ready, adding that everybody was waiting for me at the school gate.",
-      "kanji": "先生は私に、用意は出来たか、みな校門のところで君を待っているよと言った。",
-      "kana": "せんせいはわたしに、よういはできたか、みなこうもんのところできみをまっているよといった。",
-      "pieces": [
-        {
-          "lifted": "せんせい",
-          "unlifted": "先生"
-        },
-        {
-          "lifted": null,
-          "unlifted": "は"
-        },
-        {
-          "lifted": "わたし",
-          "unlifted": "私"
-        },
-        {
-          "lifted": null,
-          "unlifted": "に"
-        },
-        {
-          "lifted": "ようい",
-          "unlifted": "用意"
-        },
-        {
-          "lifted": null,
-          "unlifted": "は"
-        },
-        {
-          "lifted": "でき",
-          "unlifted": "出来た"
-        },
-        {
-          "lifted": null,
-          "unlifted": "か"
-        },
         {
           "lifted": null,
           "unlifted": "みな"
         },
         {
-          "lifted": "こうもん",
-          "unlifted": "校門"
+          "lifted": null,
+          "unlifted": "に"
         },
         {
           "lifted": null,
-          "unlifted": "の"
+          "unlifted": "こう"
+        },
+        {
+          "lifted": "よ",
+          "unlifted": "呼ばれる"
         },
         {
           "lifted": null,
-          "unlifted": "ところ"
-        },
-        {
-          "lifted": null,
-          "unlifted": "で"
-        },
-        {
-          "lifted": "きみ",
-          "unlifted": "君"
-        },
-        {
-          "lifted": null,
-          "unlifted": "を"
-        },
-        {
-          "lifted": "ま",
-          "unlifted": "待っている"
-        },
-        {
-          "lifted": null,
-          "unlifted": "よ"
-        },
-        {
-          "lifted": null,
-          "unlifted": "と"
-        },
-        {
-          "lifted": "い",
-          "unlifted": "言った"
+          "unlifted": "んだ"
         }
       ]
     },
     {
-      "english": "I will tell the teacher all about it.",
-      "kanji": "先生にみんな言いつけてやるぞ。",
-      "kana": "せんせいにみんないいつけてやるぞ。",
+      "english": "Quiet! Everybody stay where they are, there will now be a possessions check.",
+      "kanji": "静かに!みんなその場を動かないで。これから持ち物検査をはじめます。",
+      "kana": "しずかに!みんなそのばをうごかないで。これからもちものけんさをはじめます。",
       "pieces": [
         {
-          "lifted": "せんせい",
-          "unlifted": "先生"
+          "lifted": null,
+          "unlifted": "\n      "
+        },
+        {
+          "lifted": "しず",
+          "unlifted": "静かに"
         },
         {
           "lifted": null,
-          "unlifted": "に"
+          "unlifted": "!"
         },
         {
           "lifted": null,
           "unlifted": "みんな"
         },
         {
-          "lifted": "い",
-          "unlifted": "言いつけて"
+          "lifted": "そのば",
+          "unlifted": "その場"
         },
         {
           "lifted": null,
-          "unlifted": "やる"
+          "unlifted": "を"
+        },
+        {
+          "lifted": "うご",
+          "unlifted": "動かないで"
+        },
+        {
+          "lifted": null,
+          "unlifted": "。"
+        },
+        {
+          "lifted": null,
+          "unlifted": "これ"
+        },
+        {
+          "lifted": null,
+          "unlifted": "から"
+        },
+        {
+          "lifted": "もちものけんさ",
+          "unlifted": "持ち物検査"
+        },
+        {
+          "lifted": null,
+          "unlifted": "を"
+        },
+        {
+          "lifted": null,
+          "unlifted": "はじめます"
+        }
+      ]
+    },
+    {
+      "english": "All for one, and one for all. That's team play.",
+      "kanji": "一人はみんなの為に、みんなは一人の為に。それがチームプレイだ。",
+      "kana": "ひとりはみんなのために、みんなはひとりのために。それがチームプレイだ。",
+      "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
+        {
+          "lifted": "ひとり",
+          "unlifted": "一人"
+        },
+        {
+          "lifted": null,
+          "unlifted": "は"
+        },
+        {
+          "lifted": null,
+          "unlifted": "みんな"
+        },
+        {
+          "lifted": null,
+          "unlifted": "の"
+        },
+        {
+          "lifted": "ため",
+          "unlifted": "為に"
+        },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
+        {
+          "lifted": null,
+          "unlifted": "みんな"
+        },
+        {
+          "lifted": null,
+          "unlifted": "は"
+        },
+        {
+          "lifted": "ひとり",
+          "unlifted": "一人"
+        },
+        {
+          "lifted": null,
+          "unlifted": "の"
+        },
+        {
+          "lifted": "ため",
+          "unlifted": "為に"
+        },
+        {
+          "lifted": null,
+          "unlifted": "。"
+        },
+        {
+          "lifted": null,
+          "unlifted": "それ"
+        },
+        {
+          "lifted": null,
+          "unlifted": "が"
+        },
+        {
+          "lifted": null,
+          "unlifted": "チームプレイ"
+        },
+        {
+          "lifted": null,
+          "unlifted": "だ"
+        }
+      ]
+    },
+    {
+      "english": "Guys, I'll do my utmost to back you up. We'll make this event a success no matter what!",
+      "kanji": "みんな、俺も全力でフォローする。このイベントかならず成功させるぞ。",
+      "kana": "みんな、おれもぜんりょくでフォローする。このイベントかならずせいこうさせるぞ。",
+      "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
+        {
+          "lifted": null,
+          "unlifted": "みんな"
+        },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
+        {
+          "lifted": "おれ",
+          "unlifted": "俺"
+        },
+        {
+          "lifted": null,
+          "unlifted": "も"
+        },
+        {
+          "lifted": "ぜんりょく",
+          "unlifted": "全力"
+        },
+        {
+          "lifted": null,
+          "unlifted": "で"
+        },
+        {
+          "lifted": null,
+          "unlifted": "フォロー"
+        },
+        {
+          "lifted": null,
+          "unlifted": "する"
+        },
+        {
+          "lifted": null,
+          "unlifted": "。"
+        },
+        {
+          "lifted": null,
+          "unlifted": "この"
+        },
+        {
+          "lifted": null,
+          "unlifted": "イベント"
+        },
+        {
+          "lifted": null,
+          "unlifted": "かならず"
+        },
+        {
+          "lifted": "せいこう",
+          "unlifted": "成功"
+        },
+        {
+          "lifted": null,
+          "unlifted": "させる"
         },
         {
           "lifted": null,
@@ -758,76 +1106,175 @@
       ]
     },
     {
-      "english": "Everyone was silent as the teacher was announcing the results of the examination.",
-      "kanji": "先生が試験の結果を発表しているとき、みんなは沈黙していた。",
-      "kana": "せんせいがしけんのけっかをはっぴょうしているとき、みんなはちんもくしていた。",
+      "english": "Everybody has their own projects on, so after all you are the only suitable candidate.",
+      "kanji": "みなプロジェクトを抱えているので、差し詰め、君しか適任者はいない。",
+      "kana": "みなプロジェクトをかかええているので、さしずめ、きみしかてきにんしゃはいない。",
       "pieces": [
         {
-          "lifted": "せんせい",
-          "unlifted": "先生"
+          "lifted": null,
+          "unlifted": "\n      "
         },
         {
           "lifted": null,
-          "unlifted": "が"
-        },
-        {
-          "lifted": "しけん",
-          "unlifted": "試験"
+          "unlifted": "みな"
         },
         {
           "lifted": null,
-          "unlifted": "の"
-        },
-        {
-          "lifted": "けっか",
-          "unlifted": "結果"
+          "unlifted": "プロジェクト"
         },
         {
           "lifted": null,
           "unlifted": "を"
         },
         {
-          "lifted": "はっぴょう",
-          "unlifted": "発表"
+          "lifted": "かかえ",
+          "unlifted": "抱えている"
         },
         {
           "lifted": null,
-          "unlifted": "している"
+          "unlifted": "ので"
         },
         {
           "lifted": null,
-          "unlifted": "とき"
+          "unlifted": "、"
+        },
+        {
+          "lifted": "さしず",
+          "unlifted": "差し詰め"
         },
         {
           "lifted": null,
-          "unlifted": "みんな"
+          "unlifted": "、"
+        },
+        {
+          "lifted": "きみ",
+          "unlifted": "君"
+        },
+        {
+          "lifted": null,
+          "unlifted": "しか"
+        },
+        {
+          "lifted": "てきにんしゃ",
+          "unlifted": "適任者"
         },
         {
           "lifted": null,
           "unlifted": "は"
         },
-        {
-          "lifted": "ちんもく",
-          "unlifted": "沈黙"
-        },
         {
           "lifted": null,
-          "unlifted": "していた"
+          "unlifted": "いない"
         }
       ]
     },
     {
-      "english": "Not all teachers behave like that.",
-      "kanji": "先生がみんなそんなふうにふるまうわけではない。",
-      "kana": "せんせいがみんなそんなふうにふるまうわけではない。",
+      "english": "It's a very good company! The president is a real go-getter and the workers all put in their best.",
+      "kanji": "とってもいい会社ですよ。社長は凄腕だし、社員はみんな一生懸命だよ。",
+      "kana": "とってもいいかいしゃですよ。しゃちょうはすごうでだし、しゃいんはみんないっしょうけんめいだよ。",
       "pieces": [
         {
-          "lifted": "せんせい",
-          "unlifted": "先生"
+          "lifted": null,
+          "unlifted": "\n      "
         },
         {
           "lifted": null,
-          "unlifted": "が"
+          "unlifted": "とっても"
+        },
+        {
+          "lifted": null,
+          "unlifted": "いい"
+        },
+        {
+          "lifted": "かいしゃ",
+          "unlifted": "会社"
+        },
+        {
+          "lifted": null,
+          "unlifted": "です"
+        },
+        {
+          "lifted": null,
+          "unlifted": "よ"
+        },
+        {
+          "lifted": null,
+          "unlifted": "。"
+        },
+        {
+          "lifted": "しゃちょう",
+          "unlifted": "社長"
+        },
+        {
+          "lifted": null,
+          "unlifted": "は"
+        },
+        {
+          "lifted": "すごうで",
+          "unlifted": "凄腕"
+        },
+        {
+          "lifted": null,
+          "unlifted": "だ"
+        },
+        {
+          "lifted": null,
+          "unlifted": "し"
+        },
+        {
+          "lifted": null,
+          "unlifted": "、"
+        },
+        {
+          "lifted": "しゃいん",
+          "unlifted": "社員"
+        },
+        {
+          "lifted": null,
+          "unlifted": "は"
+        },
+        {
+          "lifted": null,
+          "unlifted": "みんな"
+        },
+        {
+          "lifted": "いっしょうけんめい",
+          "unlifted": "一生懸命"
+        },
+        {
+          "lifted": null,
+          "unlifted": "だ"
+        },
+        {
+          "lifted": null,
+          "unlifted": "よ"
+        }
+      ]
+    },
+    {
+      "english": "Done! Now I just have to set it to simmer so it doesn't boil before everybody comes.",
+      "kanji": "でーきた!あとはみんなが来るまで、沸騰しないように弱火にしてっと。",
+      "kana": "でーきた!あとはみんながきたるまで、ふっとうしないようによわびにしてっと。",
+      "pieces": [
+        {
+          "lifted": null,
+          "unlifted": "\n      "
+        },
+        {
+          "lifted": null,
+          "unlifted": "でーきた"
+        },
+        {
+          "lifted": null,
+          "unlifted": "!"
+        },
+        {
+          "lifted": null,
+          "unlifted": "あと"
+        },
+        {
+          "lifted": null,
+          "unlifted": "は"
         },
         {
           "lifted": null,
@@ -835,50 +1282,47 @@
         },
         {
           "lifted": null,
-          "unlifted": "そんなふうに"
+          "unlifted": "が"
+        },
+        {
+          "lifted": "きた",
+          "unlifted": "来る"
         },
         {
           "lifted": null,
-          "unlifted": "ふるまう"
+          "unlifted": "まで"
         },
         {
           "lifted": null,
-          "unlifted": "わけではない"
-        }
-      ]
-    },
-    {
-      "english": "Rabbi, that man who was with you on the other side of the Jordan - the one you testified about - well, he is baptizing, and everyone is going to him.",
-      "kanji": "先生、ごらん下さい。ヨルダンの向こうであなたと一緒にいたことがあり、そして、あなたがあかしをしておられたあのかたが、バプテスマを授けており、皆の者が、そのかたのところへ出かけています。",
-      "kana": "せんせい、ごらん下さい。ヨルダンの向こうであなたといっしょにいたことがあり、そして、あなたがあかしをしておられたあのかたが、バプテスマを授けており、皆の者が、そのかたのところへ出かけています。",
-      "pieces": [
+          "unlifted": "、"
+        },
         {
-          "lifted": "せんせい",
-          "unlifted": "先生"
+          "lifted": "ふっとう",
+          "unlifted": "沸騰"
         },
         {
           "lifted": null,
-          "unlifted": "ヨルダン"
+          "unlifted": "しない"
         },
         {
           "lifted": null,
-          "unlifted": "の"
+          "unlifted": "ように"
+        },
+        {
+          "lifted": "よわび",
+          "unlifted": "弱火"
         },
         {
           "lifted": null,
-          "unlifted": "で"
+          "unlifted": "に"
         },
         {
           "lifted": null,
-          "unlifted": "あなた"
+          "unlifted": "して"
         },
         {
           "lifted": null,
-          "unlifted": "と"
-        },
-        {
-          "lifted": "いっしょ",
-          "unlifted": "一緒に"
+          "unlifted": "っと"
         }
       ]
     }
diff --git a/test/kanji_test_cases/0.json b/test/kanji_test_cases/0.json
index 7db2fa3..d6a84b6 100644
--- a/test/kanji_test_cases/0.json
+++ b/test/kanji_test_cases/0.json
@@ -2,6 +2,7 @@
   "query": "車",
   "found": true,
   "data": {
+    "kanji": "車",
     "taughtIn": "grade 1",
     "jlptLevel": "N5",
     "newspaperFrequencyRank": 333,
@@ -20,31 +21,31 @@
         "meaning": "car, vehicle"
       },
       {
-        "example": "車検",
-        "reading": "シャケン",
-        "meaning": "vehicle inspection"
+        "example": "車庫",
+        "reading": "シャコ",
+        "meaning": "garage, carport, depot (trains, buses, etc.)"
       },
       {
-        "example": "見切り発車",
-        "reading": "ミキリハッシャ",
-        "meaning": "starting a train (or bus, etc.) before all the passengers are on board, making a snap decision, starting an action without considering objections to it any longer"
+        "example": "駐車",
+        "reading": "チュウシャ",
+        "meaning": "parking (e.g. car)"
       },
       {
-        "example": "軽自動車",
-        "reading": "ケイジドウシャ",
-        "meaning": "light motor vehicle (up to 660cc and 64bhp), k-car, kei car"
+        "example": "発車",
+        "reading": "ハッシャ",
+        "meaning": "departure (of a train, car, etc.), starting, leaving"
       }
     ],
     "kunyomiExamples": [
       {
         "example": "車",
         "reading": "くるま",
-        "meaning": "car, automobile, vehicle, wheel"
+        "meaning": "car, automobile, vehicle, wheel, castor, caster"
       },
       {
         "example": "車椅子",
         "reading": "くるまいす",
-        "meaning": "wheelchair, folding push-chair"
+        "meaning": "wheelchair"
       },
       {
         "example": "火の車",
diff --git a/test/kanji_test_cases/1.json b/test/kanji_test_cases/1.json
index 0312571..a5f1074 100644
--- a/test/kanji_test_cases/1.json
+++ b/test/kanji_test_cases/1.json
@@ -2,6 +2,7 @@
   "query": "家",
   "found": true,
   "data": {
+    "kanji": "家",
     "taughtIn": "grade 2",
     "jlptLevel": "N4",
     "newspaperFrequencyRank": 133,
@@ -23,19 +24,19 @@
         "meaning": "-ist, -er"
       },
       {
-        "example": "家屋",
-        "reading": "カオク",
-        "meaning": "house, building"
+        "example": "家族",
+        "reading": "カゾク",
+        "meaning": "family"
       },
       {
-        "example": "研究家",
-        "reading": "ケンキュウカ",
-        "meaning": "researcher, student (of)"
+        "example": "画家",
+        "reading": "ガカ",
+        "meaning": "painter, artist"
       },
       {
-        "example": "活動家",
-        "reading": "カツドウカ",
-        "meaning": "activist"
+        "example": "実業家",
+        "reading": "ジツギョウカ",
+        "meaning": "businessman, entrepreneur, captain of industry"
       },
       {
         "example": "家",
@@ -47,15 +48,15 @@
         "reading": "ケライ",
         "meaning": "retainer, retinue, servant"
       },
+      {
+        "example": "分家",
+        "reading": "ブンケ",
+        "meaning": "branch family, cadet family, establishing a branch family"
+      },
       {
         "example": "本家",
         "reading": "ホンケ",
         "meaning": "head house (family), birthplace, originator"
-      },
-      {
-        "example": "公家",
-        "reading": "クゲ",
-        "meaning": "court noble, nobility, Imperial Court"
       }
     ],
     "kunyomiExamples": [
@@ -82,23 +83,23 @@
       {
         "example": "屋",
         "reading": "や",
-        "meaning": "(something) shop, somebody who sells (something) or works as (something), somebody with a (certain) personality trait, house, roof"
+        "meaning": "shop, store, restaurant, someone who sells (something) or works as (something), someone with a (certain) personality trait, house, roof"
       },
       {
         "example": "家内",
         "reading": "かない",
         "meaning": "(my) wife, inside the home, one's family"
       },
+      {
+        "example": "隠れ家",
+        "reading": "かくれが",
+        "meaning": "hiding place, hideout, refuge, retreat, hideaway"
+      },
       {
         "example": "長屋",
         "reading": "ながや",
         "meaning": "tenement house, row house"
       },
-      {
-        "example": "本家",
-        "reading": "ほんけ",
-        "meaning": "head house (family), birthplace, originator"
-      },
       {
         "example": "家",
         "reading": "うち",
diff --git a/test/kanji_test_cases/2.json b/test/kanji_test_cases/2.json
index 56f4907..3842b41 100644
--- a/test/kanji_test_cases/2.json
+++ b/test/kanji_test_cases/2.json
@@ -2,6 +2,7 @@
   "query": "楽",
   "found": true,
   "data": {
+    "kanji": "楽",
     "taughtIn": "grade 2",
     "jlptLevel": "N4",
     "newspaperFrequencyRank": 373,
@@ -24,9 +25,9 @@
         "meaning": "music, old Japanese court music, gagaku"
       },
       {
-        "example": "楽章",
-        "reading": "ガクショウ",
-        "meaning": "(musical) movement"
+        "example": "楽譜",
+        "reading": "ガクフ",
+        "meaning": "score, sheet music"
       },
       {
         "example": "邦楽",
@@ -49,14 +50,14 @@
         "meaning": "paradise, Eden, Elysium"
       },
       {
-        "example": "千秋楽",
-        "reading": "センシュウラク",
-        "meaning": "concluding festivities, concluding program, concluding programme, final day of a tournament"
+        "example": "極楽",
+        "reading": "ゴクラク",
+        "meaning": "Sukhavati (Amitabha's Pure Land), paradise, heaven on earth"
       },
       {
-        "example": "行楽",
-        "reading": "コウラク",
-        "meaning": "outing, excursion, pleasure trip, going on a picnic"
+        "example": "享楽",
+        "reading": "キョウラク",
+        "meaning": "enjoyment, pleasure"
       },
       {
         "example": "猿楽",
diff --git a/test/kanji_test_cases/4.json b/test/kanji_test_cases/4.json
index b7c4701..555c209 100644
--- a/test/kanji_test_cases/4.json
+++ b/test/kanji_test_cases/4.json
@@ -2,6 +2,7 @@
   "query": "贄",
   "found": true,
   "data": {
+    "kanji": "贄",
     "taughtIn": null,
     "jlptLevel": null,
     "newspaperFrequencyRank": null,
diff --git a/test/kanji_test_cases/7.json b/test/kanji_test_cases/7.json
index 01996ef..04e52c5 100644
--- a/test/kanji_test_cases/7.json
+++ b/test/kanji_test_cases/7.json
@@ -2,6 +2,7 @@
   "query": "水",
   "found": true,
   "data": {
+    "kanji": "水",
     "taughtIn": "grade 1",
     "jlptLevel": "N5",
     "newspaperFrequencyRank": 223,
@@ -21,19 +22,19 @@
         "meaning": "Wednesday, shaved ice (served with flavored syrup), water (fifth of the five elements)"
       },
       {
-        "example": "水位",
-        "reading": "スイイ",
-        "meaning": "water level"
+        "example": "水曜日",
+        "reading": "スイヨウビ",
+        "meaning": "Wednesday"
       },
       {
-        "example": "用水",
-        "reading": "ヨウスイ",
-        "meaning": "irrigation water, water for fire, city water, cistern water"
+        "example": "断水",
+        "reading": "ダンスイ",
+        "meaning": "suspension of water supply, water outage"
       },
       {
-        "example": "浄水",
-        "reading": "ジョウスイ",
-        "meaning": "clean water"
+        "example": "潜水",
+        "reading": "センスイ",
+        "meaning": "diving, submerging, going underwater"
       }
     ],
     "kunyomiExamples": [
@@ -43,19 +44,19 @@
         "meaning": "water (esp. cool, fresh water, e.g. drinking water), fluid (esp. in an animal tissue), liquid, flood, floodwaters, water offered to wrestlers just prior to a bout, break granted to wrestlers engaged in a prolonged bout"
       },
       {
-        "example": "水揚げ",
-        "reading": "みずあげ",
-        "meaning": "landing, unloading (e.g. a ship), catch (of fish), takings, sales (of a shop), defloration (e.g. of a geisha), preservation (of cut flowers, in ikebana)"
+        "example": "水着",
+        "reading": "みずぎ",
+        "meaning": "bathing suit, swimsuit, swimmers"
       },
       {
-        "example": "飲み水",
-        "reading": "のみみず",
-        "meaning": "drinking water, potable water"
+        "example": "出水",
+        "reading": "しゅっすい",
+        "meaning": "flood, freshet, inundation"
       },
       {
-        "example": "呼び水",
-        "reading": "よびみず",
-        "meaning": "pump-priming, rousing, stimulation"
+        "example": "立て板に水",
+        "reading": "たていたにみず",
+        "meaning": "eloquence, volubility, (like) water on a standing board"
       }
     ],
     "radical": {
diff --git a/test/phrase_scrape_test_cases/0.json b/test/phrase_scrape_test_cases/0.json
index 65ba377..bb85c3e 100644
--- a/test/phrase_scrape_test_cases/0.json
+++ b/test/phrase_scrape_test_cases/0.json
@@ -71,6 +71,10 @@
               {
                 "lifted": null,
                 "unlifted": "ない"
+              },
+              {
+                "lifted": null,
+                "unlifted": "。"
               }
             ]
           }
@@ -83,13 +87,18 @@
       {
         "seeAlsoTerms": [],
         "sentences": [],
-        "definition": "wheel",
+        "definition": "wheel; castor; caster",
         "supplemental": [],
         "definitionAbstract": null,
         "tags": []
       }
     ],
-    "otherForms": [],
+    "otherForms": [
+      {
+        "kanji": "クルマ",
+        "kana": null
+      }
+    ],
     "audio": [
       {
         "uri": "https://d1vjc5dkcd3yh2.cloudfront.net/audio/7f47c2a8e633ca3a79ac199f55a212dd.mp3",
diff --git a/test/phrase_scrape_test_cases/1.json b/test/phrase_scrape_test_cases/1.json
index dc84fb9..ffaab21 100644
--- a/test/phrase_scrape_test_cases/1.json
+++ b/test/phrase_scrape_test_cases/1.json
@@ -10,7 +10,7 @@
       {
         "seeAlsoTerms": [],
         "sentences": [],
-        "definition": "Japanese person; Japanese people",
+        "definition": "Japanese person",
         "supplemental": [],
         "definitionAbstract": null,
         "tags": []
diff --git a/test/phrase_scrape_test_cases/2.json b/test/phrase_scrape_test_cases/2.json
index 893d814..9b635bc 100644
--- a/test/phrase_scrape_test_cases/2.json
+++ b/test/phrase_scrape_test_cases/2.json
@@ -34,6 +34,10 @@
               {
                 "lifted": "あい",
                 "unlifted": "愛されている"
+              },
+              {
+                "lifted": null,
+                "unlifted": "。"
               }
             ]
           }
@@ -71,6 +75,10 @@
               {
                 "lifted": null,
                 "unlifted": "しまった"
+              },
+              {
+                "lifted": null,
+                "unlifted": "。"
               }
             ]
           }
diff --git a/test/unofficial_jisho_api_test.dart b/test/unofficial_jisho_api_test.dart
index c0b7fa7..ea7b56b 100644
--- a/test/unofficial_jisho_api_test.dart
+++ b/test/unofficial_jisho_api_test.dart
@@ -14,9 +14,9 @@ List<String> getFilePaths(String dirname) {
       .toList();
 }
 
-List getTestCases(String directoryName) {
+List<dynamic> getTestCases(String directoryName) {
   final testCaseFiles = getFilePaths(directoryName);
-  var result = [];
+  final result = <dynamic>[];
 
   for (var testCount = 0; testCount < testCaseFiles.length; testCount++) {
     final file = File(testCaseFiles[testCount]).readAsStringSync();
@@ -27,32 +27,53 @@ List getTestCases(String directoryName) {
 
 void main() {
   group('searchForKanji', () {
-    final testCases = getTestCases('kanji_test_cases');
+    final testCases = getTestCases('kanji_test_cases')
+        .map((e) => KanjiResult.fromJson(e))
+        .toList();
     for (var testCase in testCases) {
-      test('Query "${testCase['query']}"', () async {
-        final result = await searchForKanji(testCase['query']);
-        expect(jsonEncode(result), jsonEncode(testCase));
+      test('Query "${testCase.query}"', () async {
+        final result = await searchForKanji(testCase.query);
+        expect(result, testCase);
       });
     }
   });
 
   group('searchForExamples', () {
-    final testCases = getTestCases('example_test_cases');
+    final testCases = getTestCases('example_test_cases')
+        .map((e) => ExampleResults.fromJson(e))
+        .toList();
     for (var testCase in testCases) {
-      test('Query "${testCase['query']}"', () async {
-        final result = await searchForExamples(testCase['query']);
-        expect(jsonEncode(result), jsonEncode(testCase));
+      test('Query "${testCase.query}"', () async {
+        final result = await searchForExamples(testCase.query);
+        expect(result, testCase);
       });
     }
   });
 
   group('scrapeForPhrase', () {
-    final testCases = getTestCases('phrase_scrape_test_cases');
+    final testCases = getTestCases('phrase_scrape_test_cases')
+        .map((e) => PhrasePageScrapeResult.fromJson(e))
+        .toList();
     for (var testCase in testCases) {
-      test('Query "${testCase['query']}"', () async {
-        final result = await scrapeForPhrase(testCase['query']);
-        expect(jsonEncode(result), jsonEncode(testCase));
+      test('Query "${testCase.query}"', () async {
+        final result = await scrapeForPhrase(testCase.query);
+        expect(result, testCase);
       });
     }
   });
+
+  group('equatable', () {
+    // searchForExample returns random results, not stable for testing.
+    // I will assume it works if all the other works, and rather wait for
+    // reports in Github issues if something is broken.
+    final kanjiSearch = [searchForKanji('関'), searchForKanji('関')];
+    final phraseScrape = [scrapeForPhrase('関係'), scrapeForPhrase('関係')];
+    final phraseSearch = [searchForPhrase('関係'), searchForPhrase('関係')];
+    for (var testCase in [kanjiSearch, phraseScrape, phraseSearch]) {
+      test('Equate ${testCase[0].runtimeType}' , () async {
+        expect(await testCase[0], await testCase[1]);
+      });
+    }
+  });
+
 }