1
0
mirror of https://github.com/h7x4/unofficial_jisho_api_dart.git synced 2024-12-22 12:07:29 +01:00
This commit is contained in:
Oystein Kristoffer Tveit 2020-03-08 21:11:32 +01:00
commit 5be39da75e
30 changed files with 4789 additions and 0 deletions

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
# Files and directories created by pub
.dart_tool/
.packages
# Remove the following pattern if you wish to check in your lock file
pubspec.lock
# Conventional directory for build outputs
build/
# Directory created by dartdoc
doc/api/

3
CHANGELOG.md Normal file
View File

@ -0,0 +1,3 @@
## 1.0.0
- Initial version, created by Stagehand

22
README.md Normal file
View File

@ -0,0 +1,22 @@
A library for Dart developers.
Created from templates made available by Stagehand under a BSD-style
[license](https://github.com/dart-lang/stagehand/blob/master/LICENSE).
## Usage
A simple usage example:
```dart
import 'package:unofficial_jisho_api/unofficial_jisho_api.dart';
main() {
var awesome = new Awesome();
}
```
## Features and bugs
Please file feature requests and bugs at the [issue tracker][tracker].
[tracker]: http://example.com/issues/replaceme

14
analysis_options.yaml Normal file
View File

@ -0,0 +1,14 @@
# Defines a default set of lint rules enforced for
# projects at Google. For details and rationale,
# see https://github.com/dart-lang/pedantic#enabled-lints.
include: package:pedantic/analysis_options.yaml
# For lint rules and documentation, see http://dart-lang.github.io/linter/lints.
# Uncomment to specify additional rules.
# linter:
# rules:
# - camel_case_types
analyzer:
# exclude:
# - path/to/excluded/files/**

View File

@ -0,0 +1,4 @@
import 'package:unofficial_jisho_api/unofficial_jisho_api.dart';
void main() {
}

154
lib/src/objects.dart Normal file
View File

@ -0,0 +1,154 @@
class PhraseScrapeSentence {
String english;
String japanese;
List<ExampleSentencePiece> pieces;
PhraseScrapeSentence ({String english, String japanese, List<ExampleSentencePiece> pieces}){
this.english = english;
this.japanese = japanese;
this.pieces = pieces;
}
}
class PhraseScrapeMeaning {
List<String> seeAlsoTerms;
List<PhraseScrapeSentence> sentences;
String definition;
List<String> supplemental;
String definitionAbstract;
List<String> tags;
PhraseScrapeMeaning({
List<String> seeAlsoTerms,
List<PhraseScrapeSentence> sentences,
String definition,
List<String> supplemental,
String definitionAbstract,
List<String> tags,
}){
this.seeAlsoTerms = seeAlsoTerms;
this.sentences = sentences;
this.definition = definition;
this.supplemental = supplemental;
this.definitionAbstract = definitionAbstract;
this.tags = tags;
}
}
class PhrasePageScrapeResult {
bool found;
String query;
String uri;
List<String> otherForms;
List<PhraseScrapeMeaning> meanings;
List<String> tags;
List<String> notes;
PhrasePageScrapeResult({
bool found,
String query,
String uri,
List<String> otherForms,
List<PhraseScrapeMeaning> meanings,
List<String> tags,
List<String> notes,
}){
this.found = found;
this.query = query;
this.uri = uri;
this.otherForms = otherForms;
this.meanings = meanings;
this.tags = tags;
this.notes = notes;
}
}
class YomiExample {
String example;
String reading;
String meaning;
YomiExample({String example, String reading, String meaning}){
this.example = example;
this.reading = reading;
this.meaning = meaning;
}
}
class Radical {
String symbol;
List<String> forms;
String meaning;
Radical({String symbol, List<String> forms, String meaning}){
this.symbol = symbol;
this.forms = forms;
this.meaning = meaning;
}
}
class KanjiResult {
String query;
bool found;
String taughtIn;
String jlptLevel;
int newspaperFrequencyRank;
int strokeCount;
String meaning;
List<String> kunyomi;
List<String> onyomi;
List<YomiExample> onyomiExamples;
List<YomiExample> kunyomiExamples;
Radical radical;
List<String> parts;
String strokeOrderDiagramUri;
String strokeOrderSvgUri;
String strokeOrderGifUri;
String uri;
}
class ExampleSentencePiece {
String unlifted;
String lifted;
ExampleSentencePiece({String unlifted, String lifted}){
this.unlifted = unlifted;
this.lifted = lifted;
}
}
class ExampleResultData {
String kanji;
String kana;
String english;
List<ExampleSentencePiece> pieces;
ExampleResultData({String kanji, String kana, String english, List<ExampleSentencePiece> pieces}){
this.kanji = kanji;
this.kana = kana;
this.english = english;
this.pieces = pieces;
}
}
class ExampleResults {
String query;
bool found;
String uri;
List<ExampleResultData> results;
String phrase;
ExampleResults({String query, bool found, String uri, List<ExampleResultData> results, String phrase}){
this.query = query;
this.found = found;
this.uri = uri;
this.results = results;
this.phrase = phrase;
}
}

View File

@ -0,0 +1,495 @@
import 'package:unofficial_jisho_api/src/objects.dart';
import 'package:http/http.dart' as http;
import 'package:xml/xml.dart' as xml;
import 'package:html_unescape/html_unescape.dart' as html_entities;
import 'dart:convert';
final htmlUnescape = html_entities.HtmlUnescape();
// TODO: Put public facing types in this file.
const String JISHO_API = 'http://jisho.org/api/v1/search/words';
const String SCRAPE_BASE_URI = 'http://jisho.org/search/';
const String STROKE_ORDER_DIAGRAM_BASE_URI = 'http://classic.jisho.org/static/images/stroke_diagrams/';
/* KANJI SEARCH FUNCTIONS START */
const String ONYOMI_LOCATOR_SYMBOL = 'On';
const KUNYOMI_LOCATOR_SYMBOL = 'Kun';
String removeNewlines(String str) {
return str.replaceAll(RegExp(r'(?:\r|\n)') , '').trim();
}
String uriForKanjiSearch(String kanji) {
return '${SCRAPE_BASE_URI}${Uri.encodeComponent(kanji)}%23kanji';
}
String getUriForStrokeOrderDiagram(String kanji) {
return '${STROKE_ORDER_DIAGRAM_BASE_URI}${kanji.codeUnitAt(0)}_frames.png';
}
String uriForPhraseSearch(String phrase) {
return '${JISHO_API}?keyword=${Uri.encodeComponent(phrase)}';
}
bool containsKanjiGlyph(pageHtml, String kanji) {
final kanjiGlyphToken = '<h1 class="character" data-area-name="print" lang="ja">${kanji}</h1>';
return pageHtml.indexOf(kanjiGlyphToken) != -1;
}
String getStringBetweenIndicies(String data, int startIndex, int endIndex) {
final result = data.substring(startIndex, endIndex);
return removeNewlines(result).trim();
}
String getStringBetweenStrings(String data, String startString, String endString) {
final regex = RegExp('${RegExp.escape(startString)}(.*?)${RegExp.escape(endString)}');
final match = regex.allMatches(data).toList();
return match ?? match[1].toString();
}
int getIntBetweenStrings(pageHtml, String startString, String endString) {
final stringBetweenStrings = getStringBetweenStrings(pageHtml, startString, endString);
return stringBetweenStrings ?? int.parse(stringBetweenStrings);
}
List<String> getAllGlobalGroupMatches(String str, RegExp regex) {
var regexResults = regex.allMatches(str).toList();
var results = [];
for (var match in regexResults) {
results.add(match.toString().split(' ')[0]);
}
return results;
}
List<String> parseAnchorsToArray(String str) {
final regex = RegExp(r'<a href=".*?">(.*?)<\/a>');
return getAllGlobalGroupMatches(str, regex);
}
List<String> getYomi(pageHtml, String yomiLocatorSymbol) {
final yomiSection = getStringBetweenStrings(pageHtml, '<dt>${yomiLocatorSymbol}:</dt>', '</dl>');
return parseAnchorsToArray(yomiSection ?? '');
}
List<String> getKunyomi(pageHtml) {
return getYomi(pageHtml, KUNYOMI_LOCATOR_SYMBOL);
}
List<String> getOnyomi(pageHtml) {
return getYomi(pageHtml, ONYOMI_LOCATOR_SYMBOL);
}
List<YomiExample> getYomiExamples(pageHtml, String yomiLocatorSymbol) {
final locatorString = '<h2>${yomiLocatorSymbol} reading compounds</h2>';
final exampleSection = getStringBetweenStrings(pageHtml, locatorString, '</ul>');
if (exampleSection==null) {
return null;
}
final regex = RegExp(r'/<li>(.*?)<\/li>');
final regexResults = getAllGlobalGroupMatches(exampleSection, regex).map((s) => s.trim());
final examples = regexResults.map((regexResult) {
final examplesLines = regexResult.split('\n').map((s) => s.trim()).toList();
return YomiExample(
example: examplesLines[0],
reading: examplesLines[1].replaceAll('', '').replaceAll('', ''),
meaning: htmlUnescape.convert(examplesLines[2]),
);
});
return examples;
}
List<YomiExample> getOnyomiExamples(pageHtml) {
return getYomiExamples(pageHtml, ONYOMI_LOCATOR_SYMBOL);
}
List<YomiExample> getKunyomiExamples(pageHtml) {
return getYomiExamples(pageHtml, KUNYOMI_LOCATOR_SYMBOL);
}
Radical getRadical(pageHtml) {
const radicalMeaningStartString = '<span class="radical_meaning">';
const radicalMeaningEndString = '</span>';
var radicalMeaning = getStringBetweenStrings(
pageHtml,
radicalMeaningStartString,
radicalMeaningEndString,
).trim();
if (radicalMeaning!=null) {
final radicalMeaningStartIndex = pageHtml.indexOf(radicalMeaningStartString);
final radicalMeaningEndIndex = pageHtml.indexOf(
radicalMeaningEndString,
radicalMeaningStartIndex,
);
final radicalSymbolStartIndex = radicalMeaningEndIndex + radicalMeaningEndString.length;
const radicalSymbolEndString = '</span>';
final radicalSymbolEndIndex = pageHtml.indexOf(radicalSymbolEndString, radicalSymbolStartIndex);
final radicalSymbolsString = getStringBetweenIndicies(
pageHtml,
radicalSymbolStartIndex,
radicalSymbolEndIndex,
);
if (radicalSymbolsString.length > 1) {
final radicalForms = radicalSymbolsString
.substring(1)
.replaceAll('(', '')
.replaceAll(')', '')
.trim()
.split(', ');
return Radical(
symbol: radicalSymbolsString[0],
forms: radicalForms,
meaning: radicalMeaning
);
}
return Radical (
symbol: radicalSymbolsString,
meaning: radicalMeaning
);
}
return null;
}
List<String> getParts(pageHtml) {
const partsSectionStartString = '<dt>Parts:</dt>';
const partsSectionEndString = '</dl>';
final partsSection = getStringBetweenStrings(
pageHtml,
partsSectionStartString,
partsSectionEndString,
);
var result = parseAnchorsToArray(partsSection);
result.sort();
return (result);
}
String getSvgUri(pageHtml) {
var svgRegex = RegExp('\/\/.*?.cloudfront.net\/.*?.svg/');
final regexResult = svgRegex.firstMatch(pageHtml).toString();
return regexResult ?? 'http:${regexResult}';
}
String getGifUri(String kanji) {
final unicodeString = kanji.codeUnitAt(0).toRadixString(16);
final fileName = '${unicodeString}.gif';
final animationUri = 'https://raw.githubusercontent.com/mistval/kanji_images/master/gifs/${fileName}';
return animationUri;
}
int getNewspaperFrequencyRank(pageHtml) {
final frequencySection = getStringBetweenStrings(pageHtml, '<div class="frequency">', '</div>');
return frequencySection ?? int.parse(getStringBetweenStrings(frequencySection, '<strong>', '</strong>'));
}
KanjiResult parseKanjiPageData(pageHtml, String kanji) {
final result = KanjiResult();
result.query = kanji;
result.found = containsKanjiGlyph(pageHtml, kanji);
if (result.found==false) {
return result;
}
result.taughtIn = getStringBetweenStrings(pageHtml, 'taught in <strong>', '</strong>');
result.jlptLevel = getStringBetweenStrings(pageHtml, 'JLPT level <strong>', '</strong>');
result.newspaperFrequencyRank = getNewspaperFrequencyRank(pageHtml);
result.strokeCount = getIntBetweenStrings(pageHtml, '<strong>', '</strong> strokes');
result.meaning = htmlUnescape.convert(removeNewlines(getStringBetweenStrings(pageHtml, '<div class="kanji-details__main-meanings">', '</div>')).trim());
result.kunyomi = getKunyomi(pageHtml);
result.onyomi = getOnyomi(pageHtml);
result.onyomiExamples = getOnyomiExamples(pageHtml);
result.kunyomiExamples = getKunyomiExamples(pageHtml);
result.radical = getRadical(pageHtml);
result.parts = getParts(pageHtml);
result.strokeOrderDiagramUri = getUriForStrokeOrderDiagram(kanji);
result.strokeOrderSvgUri = getSvgUri(pageHtml);
result.strokeOrderGifUri = getGifUri(kanji);
result.uri = uriForKanjiSearch(kanji);
return result;
}
/* KANJI SEARCH FUNCTIONS END */
/* EXAMPLE SEARCH FUNCTIONS START */
RegExp kanjiRegex = RegExp(r'[\u4e00-\u9faf\u3400-\u4dbf]');
String uriForExampleSearch(String phrase) {
return '${SCRAPE_BASE_URI}${Uri.encodeComponent(phrase)}%23sentences';
}
ExampleResultData getKanjiAndKana(div) {
final ul = div.find('ul').eq(0);
final contents = ul.contents();
var kanji = '';
var kana = '';
for (var i = 0; i < contents.length; i += 1) {
final content = contents.eq(i);
if (content[0].name == 'li') {
final li = content;
final furigana = li.find('.furigana').text();
final unlifted = li.find('.unlinked').text();
if (furigana) {
kanji += unlifted;
kana += furigana;
final kanaEnding = [];
for (var j = unlifted.length - 1; j > 0; j -= 1) {
if (!unlifted[j].match(kanjiRegex)) {
kanaEnding.add(unlifted[j]);
} else {
break;
}
}
kana += kanaEnding.reversed.join('');
} else {
kanji += unlifted;
kana += unlifted;
}
} else {
final text = content.text().trim();
if (text) {
kanji += text;
kana += text;
}
}
}
return ExampleResultData(
kanji: kanji,
kana: kana,
);
}
List<ExampleSentencePiece> getPieces(sentenceElement) {
final pieceElements = sentenceElement.find('li.clearfix');
final pieces = [];
for (var pieceIndex = 0; pieceIndex < pieceElements.length; pieceIndex += 1) {
final pieceElement = pieceElements.eq(pieceIndex);
pieces.add(ExampleSentencePiece(
lifted: pieceElement.children('.furigana').text(),
unlifted: pieceElement.children('.unlinked').text(),
));
}
return pieces;
}
ExampleResultData parseExampleDiv(div) {
final result = getKanjiAndKana(div);
result.english = div.find('.english').text();
result.pieces = getPieces(div);
return result;
}
ExampleResults parseExamplePageData(pageHtml, String phrase) {
final document = xml.parse(pageHtml);
final divs = document.descendants.where((node) => node.attributes[0].value == 'sentence_content').toList();
final results = divs.map((div) => parseExampleDiv(div));
return ExampleResults(
query: phrase,
found: results.isNotEmpty,
results: results,
uri: uriForExampleSearch(phrase),
phrase: phrase,
);
}
/* EXAMPLE SEARCH FUNCTIONS END */
/* PHRASE SCRAPE FUNCTIONS START */
List<String> getTags(document) {
final tags = [];
final tagElements = document.descendants.where((node) => node.attributes[0].value == 'concept_light-tag').toList();
for (var i = 0; i < tagElements.length; i += 1) {
final tagText = tagElements.eq(i).text();
tags.add(tagText);
}
return tags;
}
PhrasePageScrapeResult getMeaningsOtherFormsAndNotes(document) {
final returnValues = PhrasePageScrapeResult( otherForms: [], notes: [] );
//TODO: Fix
// const meaningsWrapper = $('#page_container > div > div > article > div > div.concept_light-meanings.medium-9.columns > div');
final meaningsWrapper = document.descendants.where((node) => node.attributes[0].value == 'page_container').toList();
final meaningsChildren = meaningsWrapper.children();
final meanings = [];
var mostRecentWordTypes = [];
for (var meaningIndex = 0; meaningIndex < meaningsChildren.length; meaningIndex += 1) {
final child = meaningsChildren.eq(meaningIndex);
if (child.hasClass('meaning-tags')) {
mostRecentWordTypes = child.text().split(',').map((s) => s.trim().toLowerCase());
} else if (mostRecentWordTypes[0] == 'other forms') {
returnValues.otherForms = child.text().split('')
.map((s) => s.replaceAll('', '').replaceAll('', '').split(' '))
.map((a) => (ExampleResultData( kanji: a[0], kana: a[1] )));
} else if (mostRecentWordTypes[0] == 'notes') {
returnValues.notes = child.text().split('\n');
} else {
final meaning = child.find('.meaning-meaning').text();
final meaningAbstract = child.find('.meaning-abstract')
.find('a')
.remove()
.end()
.text();
final supplemental = child.find('.supplemental_info').text().split(',')
.map((s) => s.trim())
.filter((s) => s);
final seeAlsoTerms = [];
for (var i = supplemental.length - 1; i >= 0; i -= 1) {
final supplementalEntry = supplemental[i];
if (supplementalEntry.startsWith('See also')) {
seeAlsoTerms.add(supplementalEntry.replaceAll('See also ', ''));
supplemental.splice(i, 1);
}
}
final sentences = [];
final sentenceElements = child.find('.sentences').children('.sentence');
for (var sentenceIndex = 0; sentenceIndex < sentenceElements.length; sentenceIndex += 1) {
final sentenceElement = sentenceElements.eq(sentenceIndex);
final english = sentenceElement.find('.english').text();
final pieces = getPieces(sentenceElement);
final japanese = sentenceElement
.find('.english').remove().end()
.find('.furigana')
.remove()
.end()
.text();
sentences.add(PhraseScrapeSentence(english: english, japanese: japanese, pieces: pieces));
}
meanings.add(PhraseScrapeMeaning(
seeAlsoTerms: seeAlsoTerms,
sentences: sentences,
definition: meaning,
supplemental: supplemental,
definitionAbstract: meaningAbstract,
tags: mostRecentWordTypes,
));
}
}
returnValues.meanings = meanings;
return returnValues;
}
String uriForPhraseScrape(searchTerm) {
return 'https://jisho.org/word/${Uri.encodeComponent(searchTerm)}';
}
PhrasePageScrapeResult parsePhrasePageData(pageHtml, query) {
final document = xml.parse(pageHtml);
final result = getMeaningsOtherFormsAndNotes(document);
result.found = true;
result.query = query;
result.uri = uriForPhraseScrape(query);
result.tags = getTags(document);
// result.meanings = meanings;
// result.otherForms = forms;
// result.notes = notes;
return result;
}
class API {
/// Query the official Jisho API for a word or phrase
///
/// See [here]{@link https://jisho.org/forum/54fefc1f6e73340b1f160000-is-there-any-kind-of-search-api}
/// for discussion about the official API.
/// @param {string} phrase The search term to search for.
/// @returns {Object} The response data from the official Jisho.org API. Its format is somewhat
/// complex and is not documented, so put on your trial-and-error hat.
/// @async
searchForPhrase(String phrase) {
final uri = uriForPhraseSearch(phrase);
return http.read(uri).then((response) => jsonDecode(response).data);
}
/// Scrape the word page for a word/phrase.
///
/// This allows you to get some information that isn't provided by the official API, such as
/// part-of-speech and JLPT level. However, the official API should be preferred
/// if it has the information you need. This function scrapes https://jisho.org/word/XXX.
/// In general, you'll want to include kanji in your search term, for example 掛かる
/// instead of (no results).
/// @param {string} phrase The search term to search for.
/// @returns {PhrasePageScrapeResult} Information about the searched query.
/// @async
Future<PhrasePageScrapeResult> scrapeForPhrase(String phrase) async {
final uri = uriForPhraseScrape(phrase);
try {
final response = await http.read(uri);
return parsePhrasePageData(jsonDecode(response).data, phrase);
} catch (err) {
if (err.response.status == 404) {
return PhrasePageScrapeResult(
query: phrase,
found: false,
);
}
throw err;
}
}
/// Scrape Jisho.org for information about a kanji character.
/// @param {string} kanji The kanji to search for.
/// @returns {KanjiResult} Information about the searched kanji.
/// @async
Future<KanjiResult> searchForKanji(String kanji) {
final uri = uriForKanjiSearch(kanji);
return http.read(uri).then((response) => parseKanjiPageData(jsonDecode(response).data, kanji));
}
/// Scrape Jisho.org for examples.
/// @param {string} phrase The word or phrase to search for.
/// @returns {ExampleResults}
/// @async
Future<ExampleResults> searchForExamples(String phrase) {
final uri = uriForExampleSearch(phrase);
return http.read(uri).then((response) => parseExamplePageData(jsonDecode(response).data, phrase));
}
}

View File

@ -0,0 +1,7 @@
/// Support for doing something awesome.
///
/// More dartdocs go here.
library unofficial_jisho_api;
export 'src/unofficial_jisho_api_base.dart';

16
pubspec.yaml Normal file
View File

@ -0,0 +1,16 @@
name: unofficial_jisho_api
description: A starting point for Dart libraries or applications.
version: 1.0.0
homepage: https://www.example.com #TODO: EDIT
environment:
sdk: '>=2.7.0 <3.0.0'
dependencies:
# path: ^1.6.0
xml: ^3.7.0
html_unescape: ^1.0.1+3
dev_dependencies:
pedantic: ^1.8.0
test: ^1.6.0

View File

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,891 @@
{
"query": "日本人",
"expectedResult": {
"query": "日本人",
"found": true,
"results": [
{
"english": "A Japanese person would never do such a thing.",
"kanji": "日本人ならそんなことはけっしてしないでしょう。",
"kana": "にほんじんならそんなことはけっしてしないでしょう。",
"pieces": [
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "なら"
},
{
"lifted": "",
"unlifted": "そんな"
},
{
"lifted": "",
"unlifted": "こと"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "",
"unlifted": "けっして"
},
{
"lifted": "",
"unlifted": "しない"
},
{
"lifted": "",
"unlifted": "でしょう"
}
]
},
{
"english": "When did the Japanese start eating polished rice?",
"kanji": "いつから日本人は精白米を食べるようになったのですか?",
"kana": "いつからにほんじんはせいはくまいをたべるようになったのですか?",
"pieces": [
{
"lifted": "",
"unlifted": "いつから"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "せいはくまい",
"unlifted": "精白米"
},
{
"lifted": "",
"unlifted": "を"
},
{
"lifted": "た",
"unlifted": "食べる"
},
{
"lifted": "",
"unlifted": "ようになった"
},
{
"lifted": "",
"unlifted": "のです"
},
{
"lifted": "",
"unlifted": "か"
}
]
},
{
"english": "I think there are probably few Japanese who know this side of the Emperor Meiji, the side that left a song like this.",
"kanji": "こんな歌を残している明治天皇の一面を知っている日本人は少ないのではないだろうか。",
"kana": "こんなうたをのこしているめいじてんのうのいちめんをしっているにほんじんはすくないのではないだろうか。",
"pieces": [
{
"lifted": "",
"unlifted": "こんな"
},
{
"lifted": "うた",
"unlifted": "歌"
},
{
"lifted": "",
"unlifted": "を"
},
{
"lifted": "のこ",
"unlifted": "残している"
},
{
"lifted": "めいじてんのう",
"unlifted": "明治天皇"
},
{
"lifted": "",
"unlifted": "の"
},
{
"lifted": "いちめん",
"unlifted": "一面"
},
{
"lifted": "",
"unlifted": "を"
},
{
"lifted": "し",
"unlifted": "知っている"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "すく",
"unlifted": "少ない"
},
{
"lifted": "",
"unlifted": "の"
},
{
"lifted": "",
"unlifted": "ではない"
},
{
"lifted": "",
"unlifted": "だろうか"
}
]
},
{
"english": "I'm Japanese, but I don't live in Japan.",
"kanji": "私は日本人ですが、日本に住んでいません。",
"kana": "わたしはにほんじんですが、にほんにすんでいません。",
"pieces": [
{
"lifted": "わたし",
"unlifted": "私"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "です"
},
{
"lifted": "",
"unlifted": "が"
},
{
"lifted": "にほん",
"unlifted": "日本"
},
{
"lifted": "",
"unlifted": "に"
},
{
"lifted": "す",
"unlifted": "住んでいません"
}
]
},
{
"english": "They don't use 'celeb' to mean 'rich man' over there. By which I determine that you are Japanese.",
"kanji": "向こうではセレブという言葉を「金持ち」の意味では使わない。という事で日本人と判明しました。",
"kana": "むこうではセレブということばを「かねもち」のいみではつかわない。ということでにほんじんとはんめいしました。",
"pieces": [
{
"lifted": "む",
"unlifted": "向こう"
},
{
"lifted": "",
"unlifted": "で"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "",
"unlifted": "セレブ"
},
{
"lifted": "",
"unlifted": "という"
},
{
"lifted": "ことば",
"unlifted": "言葉"
},
{
"lifted": "",
"unlifted": "を"
},
{
"lifted": "かねも",
"unlifted": "金持ち"
},
{
"lifted": "",
"unlifted": "の"
},
{
"lifted": "いみ",
"unlifted": "意味"
},
{
"lifted": "",
"unlifted": "で"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "つか",
"unlifted": "使わない"
},
{
"lifted": "",
"unlifted": "と"
},
{
"lifted": "",
"unlifted": "いう"
},
{
"lifted": "こと",
"unlifted": "事"
},
{
"lifted": "",
"unlifted": "で"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "と"
},
{
"lifted": "はんめい",
"unlifted": "判明"
},
{
"lifted": "",
"unlifted": "しました"
}
]
},
{
"english": "As you can also tell from these beautiful, far from Japanese, looks, Yuna is not pure-blood Japanese. She's a quarter-blood with a westerner as grandmother.",
"kanji": "日本人離れしたこの美しい相貌からもわかるように、優奈は実は生粋の日本人じゃない。西洋人をおばあちゃんに持つ、クォーターだったりする。",
"kana": "にほんじんはなれしたこのうつくしいそうぼうからもわかるように、優奈はじつはきっすいのにほんじんじゃない。せいようじんをおばあちゃんにもつ、クォーターだったりする。",
"pieces": [
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "はな",
"unlifted": "離れ"
},
{
"lifted": "",
"unlifted": "した"
},
{
"lifted": "",
"unlifted": "この"
},
{
"lifted": "うつく",
"unlifted": "美しい"
},
{
"lifted": "そうぼう",
"unlifted": "相貌"
},
{
"lifted": "",
"unlifted": "から"
},
{
"lifted": "",
"unlifted": "も"
},
{
"lifted": "",
"unlifted": "わかる"
},
{
"lifted": "",
"unlifted": "ように"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "じつ",
"unlifted": "実は"
},
{
"lifted": "きっすい",
"unlifted": "生粋の"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "じゃない"
},
{
"lifted": "せいようじん",
"unlifted": "西洋人"
},
{
"lifted": "",
"unlifted": "を"
},
{
"lifted": "",
"unlifted": "おばあちゃん"
},
{
"lifted": "",
"unlifted": "に"
},
{
"lifted": "も",
"unlifted": "持つ"
},
{
"lifted": "",
"unlifted": "クォーター"
},
{
"lifted": "",
"unlifted": "だったり"
},
{
"lifted": "",
"unlifted": "する"
}
]
},
{
"english": "Today's topic is \"the problem of Japanese people abducted by North Korea\".",
"kanji": "今日のトピックは「北朝鮮による日本人拉致問題」です。",
"kana": "きょうのトピックは「きたちょうせんによるにほんじんらちもんだい」です。",
"pieces": [
{
"lifted": "きょう",
"unlifted": "今日"
},
{
"lifted": "",
"unlifted": "の"
},
{
"lifted": "",
"unlifted": "トピック"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "きたちょうせん",
"unlifted": "北朝鮮"
},
{
"lifted": "",
"unlifted": "による"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "らち",
"unlifted": "拉致"
},
{
"lifted": "もんだい",
"unlifted": "問題"
},
{
"lifted": "",
"unlifted": "です"
}
]
},
{
"english": "Foreign rice is hard and tasteless, and doesn't appeal to the Japanese palate.",
"kanji": "外米はぼそぼそしていて、日本人の口には合わない。",
"kana": "がいまいはぼそぼそしていて、にほんじんのくちにはあわない。",
"pieces": [
{
"lifted": "がいまい",
"unlifted": "外米"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "",
"unlifted": "ぼそぼそ"
},
{
"lifted": "",
"unlifted": "していて"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "の"
},
{
"lifted": "くち",
"unlifted": "口"
},
{
"lifted": "",
"unlifted": "には"
},
{
"lifted": "あ",
"unlifted": "合わない"
}
]
},
{
"english": "A number of Japanese people travel abroad every summer.",
"kanji": "毎年、多くの日本人が海外へ旅行する。",
"kana": "まいとし、おおくのにほんじんがかいがいへりょこうする。",
"pieces": [
{
"lifted": "まいとし",
"unlifted": "毎年"
},
{
"lifted": "おお",
"unlifted": "多く"
},
{
"lifted": "",
"unlifted": "の"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "が"
},
{
"lifted": "かいがい",
"unlifted": "海外"
},
{
"lifted": "",
"unlifted": "へ"
},
{
"lifted": "りょこう",
"unlifted": "旅行"
},
{
"lifted": "",
"unlifted": "する"
}
]
},
{
"english": "Her father is Japanese.",
"kanji": "彼女の父親は日本人だ。",
"kana": "かのじょのちちおやはにほんじんだ。",
"pieces": [
{
"lifted": "かのじょ",
"unlifted": "彼女の"
},
{
"lifted": "ちちおや",
"unlifted": "父親"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "だ"
}
]
},
{
"english": "They employ foreigners because Japanese workers are in short supply.",
"kanji": "彼らは日本人労働者が不足しているから外国人を雇う。",
"kana": "かれらはにほんじんろうどうしゃがふそくしているからがいこくじんをやとう。",
"pieces": [
{
"lifted": "かれ",
"unlifted": "彼ら"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "ろうどうしゃ",
"unlifted": "労働者"
},
{
"lifted": "",
"unlifted": "が"
},
{
"lifted": "ふそく",
"unlifted": "不足"
},
{
"lifted": "",
"unlifted": "している"
},
{
"lifted": "",
"unlifted": "から"
},
{
"lifted": "がいこくじん",
"unlifted": "外国人"
},
{
"lifted": "",
"unlifted": "を"
},
{
"lifted": "やと",
"unlifted": "雇う"
}
]
},
{
"english": "Are they Japanese?",
"kanji": "彼らは日本人ですか。",
"kana": "かれらはにほんじんですか。",
"pieces": [
{
"lifted": "かれ",
"unlifted": "彼ら"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "ですか"
}
]
},
{
"english": "Are they Japanese or Chinese?",
"kanji": "彼らは日本人ですか、それとも中国人ですか。",
"kana": "かれらはにほんじんですか、それともちゅうごくじんですか。",
"pieces": [
{
"lifted": "かれ",
"unlifted": "彼ら"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "ですか"
},
{
"lifted": "",
"unlifted": "それとも"
},
{
"lifted": "ちゅうごくじん",
"unlifted": "中国人"
},
{
"lifted": "",
"unlifted": "ですか"
}
]
},
{
"english": "He is not Japanese.",
"kanji": "彼は日本人ではありません。",
"kana": "かれはにほんじんではありません。",
"pieces": [
{
"lifted": "かれ",
"unlifted": "彼"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "ではありません"
}
]
},
{
"english": "He speaks Japanese as if he were Japanese.",
"kanji": "彼は日本語をまるで日本人であるかのように話す。",
"kana": "かれはにほんごをまるでにほんじんであるかのようにはなす。",
"pieces": [
{
"lifted": "かれ",
"unlifted": "彼"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "にほんご",
"unlifted": "日本語"
},
{
"lifted": "",
"unlifted": "を"
},
{
"lifted": "",
"unlifted": "まるで"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "である"
},
{
"lifted": "",
"unlifted": "かのように"
},
{
"lifted": "はな",
"unlifted": "話す"
}
]
},
{
"english": "He is a typical Japanese.",
"kanji": "彼は典型的な日本人だ。",
"kana": "かれはてんけいてきなにほんじんだ。",
"pieces": [
{
"lifted": "かれ",
"unlifted": "彼"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "てんけいてき",
"unlifted": "典型的な"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "だ"
}
]
},
{
"english": "He is Japanese by birth.",
"kanji": "彼は生まれは日本人です。",
"kana": "かれはうまれはにほんじんです。",
"pieces": [
{
"lifted": "かれ",
"unlifted": "彼"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "う",
"unlifted": "生まれ"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "です"
}
]
},
{
"english": "He is the first Japanese that traveled in space.",
"kanji": "彼は最初に宇宙旅行をした日本人です。",
"kana": "かれはさいしょにうちゅうりょこうをしたにほんじんです。",
"pieces": [
{
"lifted": "かれ",
"unlifted": "彼"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "さいしょ",
"unlifted": "最初"
},
{
"lifted": "",
"unlifted": "に"
},
{
"lifted": "うちゅうりょこう",
"unlifted": "宇宙旅行"
},
{
"lifted": "",
"unlifted": "を"
},
{
"lifted": "",
"unlifted": "した"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "です"
}
]
},
{
"english": "He is Japanese to the bone.",
"kanji": "彼は骨の髄まで日本人だ。",
"kana": "かれはほねのずいまでにほんじんだ。",
"pieces": [
{
"lifted": "かれ",
"unlifted": "彼"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "ほねのずい",
"unlifted": "骨の髄まで"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "だ"
}
]
},
{
"english": "He speaks Japanese as if he were Japanese.",
"kanji": "彼は、日本語をまるで日本人かのように話す。",
"kana": "かれは、にほんごをまるでにほんじんかのようにはなす。",
"pieces": [
{
"lifted": "かれ",
"unlifted": "彼"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "にほんご",
"unlifted": "日本語"
},
{
"lifted": "",
"unlifted": "を"
},
{
"lifted": "",
"unlifted": "まるで"
},
{
"lifted": "にほんじん",
"unlifted": "日本人"
},
{
"lifted": "",
"unlifted": "かのように"
},
{
"lifted": "はな",
"unlifted": "話す"
}
]
}
],
"uri": "http://jisho.org/search/%E6%97%A5%E6%9C%AC%E4%BA%BA%23sentences",
"phrase": "日本人"
}
}

View File

@ -0,0 +1,10 @@
{
"query": "彼*叩く",
"expectedResult": {
"query": "彼*叩く",
"found": false,
"results": [],
"uri": "http://jisho.org/search/%E5%BD%BC%EF%BC%8A%E5%8F%A9%E3%81%8F%23sentences",
"phrase": "彼*叩く"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
{
"query": "ネガティブ",
"expectedResult": {
"query": "ネガティブ",
"found": false,
"results": [],
"uri": "http://jisho.org/search/%E3%83%8D%E3%82%AC%E3%83%86%E3%82%A3%E3%83%96%23sentences",
"phrase": "ネガティブ"
}
}

View File

@ -0,0 +1,10 @@
{
"query": "grlgmregmneriireg",
"expectedResult": {
"query": "grlgmregmneriireg",
"found": false,
"results": [],
"uri": "http://jisho.org/search/grlgmregmneriireg%23sentences",
"phrase": "grlgmregmneriireg"
}
}

View File

@ -0,0 +1,68 @@
{
"query": "車",
"expectedResult": {
"query": "車",
"found": true,
"taughtIn": "grade 1",
"jlptLevel": "N5",
"newspaperFrequencyRank": "333",
"strokeCount": 7,
"meaning": "car",
"kunyomi": [
"くるま"
],
"onyomi": [
"シャ"
],
"onyomiExamples": [
{
"example": "車",
"reading": "シャ",
"meaning": "car, vehicle"
},
{
"example": "車検",
"reading": "シャケン",
"meaning": "vehicle inspection"
},
{
"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": "light motor vehicle (up to 660cc and 64bhp), k-car, kei car"
}
],
"kunyomiExamples": [
{
"example": "車",
"reading": "くるま",
"meaning": "car, automobile, vehicle, wheel"
},
{
"example": "車椅子",
"reading": "くるまいす",
"meaning": "wheelchair, folding push-chair"
},
{
"example": "火の車",
"reading": "ひのくるま",
"meaning": "fiery chariot (which carries the souls of sinners into hell), desperate financial situation, dire straits"
}
],
"radical": {
"symbol": "車",
"meaning": "cart, car"
},
"parts": [
"車"
],
"strokeOrderDiagramUri": "http://classic.jisho.org/static/images/stroke_diagrams/36554_frames.png",
"strokeOrderSvgUri": "http://d1w6u4xc3l95km.cloudfront.net/kanji-2015-03/08eca.svg",
"strokeOrderGifUri": "https://raw.githubusercontent.com/mistval/kanji_images/master/gifs/8eca.gif",
"uri": "http://jisho.org/search/%E8%BB%8A%23kanji"
}
}

View File

@ -0,0 +1,127 @@
{
"query": "家",
"expectedResult": {
"query": "家",
"found": true,
"taughtIn": "grade 2",
"jlptLevel": "N4",
"newspaperFrequencyRank": "133",
"strokeCount": 10,
"meaning": "house, home, family, professional, expert, performer",
"kunyomi": [
"いえ",
"や",
"うち"
],
"onyomi": [
"カ",
"ケ"
],
"onyomiExamples": [
{
"example": "家",
"reading": "カ",
"meaning": "-ist, -er"
},
{
"example": "家屋",
"reading": "カオク",
"meaning": "house, building"
},
{
"example": "研究家",
"reading": "ケンキュウカ",
"meaning": "researcher, student (of)"
},
{
"example": "活動家",
"reading": "カツドウカ",
"meaning": "activist"
},
{
"example": "家",
"reading": "ケ",
"meaning": "house (e.g. of Tokugawa), family"
},
{
"example": "家来",
"reading": "ケライ",
"meaning": "retainer, retinue, servant"
},
{
"example": "本家",
"reading": "ホンケ",
"meaning": "head house (family), birthplace, originator"
},
{
"example": "公家",
"reading": "クゲ",
"meaning": "court noble, nobility, Imperial Court"
}
],
"kunyomiExamples": [
{
"example": "家",
"reading": "いえ",
"meaning": "house, residence, dwelling, family, household, lineage, family name"
},
{
"example": "家主",
"reading": "やぬし",
"meaning": "landlord, landlady, house owner, home owner, head of the household"
},
{
"example": "本家",
"reading": "ほんけ",
"meaning": "head house (family), birthplace, originator"
},
{
"example": "小家",
"reading": "こいえ",
"meaning": "small and simple home"
},
{
"example": "屋",
"reading": "や",
"meaning": "(something) shop, somebody who sells (something) or works as (something), somebody with a (certain) personality trait, house, roof"
},
{
"example": "家内",
"reading": "かない",
"meaning": "(my) wife, inside the home, one's family"
},
{
"example": "長屋",
"reading": "ながや",
"meaning": "tenement house, row house"
},
{
"example": "本家",
"reading": "ほんけ",
"meaning": "head house (family), birthplace, originator"
},
{
"example": "家",
"reading": "うち",
"meaning": "house, home (one's own), (one's) family, (one's) household"
},
{
"example": "家中",
"reading": "うちじゅう",
"meaning": "whole family, all (members of) the family, all over the house, retainer of a daimyo, feudal domain, clan"
}
],
"radical": {
"symbol": "宀",
"meaning": "roof"
},
"parts": [
"宀",
"豕"
],
"strokeOrderDiagramUri": "http://classic.jisho.org/static/images/stroke_diagrams/23478_frames.png",
"strokeOrderSvgUri": "http://d1w6u4xc3l95km.cloudfront.net/kanji-2015-03/05bb6.svg",
"strokeOrderGifUri": "https://raw.githubusercontent.com/mistval/kanji_images/master/gifs/5bb6.gif",
"uri": "http://jisho.org/search/%E5%AE%B6%23kanji"
}
}

View File

@ -0,0 +1,99 @@
{
"query": "楽",
"expectedResult": {
"query": "楽",
"found": true,
"taughtIn": "grade 2",
"jlptLevel": "N4",
"newspaperFrequencyRank": "373",
"strokeCount": 13,
"meaning": "music, comfort, ease",
"kunyomi": [
"たの.しい",
"たの.しむ",
"この.む"
],
"onyomi": [
"ガク",
"ラク",
"ゴウ"
],
"onyomiExamples": [
{
"example": "楽団",
"reading": "ガクダン",
"meaning": "orchestra, band"
},
{
"example": "楽章",
"reading": "ガクショウ",
"meaning": "(musical) movement"
},
{
"example": "邦楽",
"reading": "ホウガク",
"meaning": "Japanese music (esp. traditional Japanese music)"
},
{
"example": "室内楽",
"reading": "シツナイガク",
"meaning": "chamber music"
},
{
"example": "楽",
"reading": "ラク",
"meaning": "comfort, ease, relief, (at) peace, relaxation, easy, simple, without trouble, without hardships, (economically) comfortable, raku pottery"
},
{
"example": "楽園",
"reading": "ラクエン",
"meaning": "pleasure garden, paradise"
},
{
"example": "千秋楽",
"reading": "センシュウラク",
"meaning": "concluding festivities, concluding program, concluding programme, final day of a tournament"
},
{
"example": "行楽",
"reading": "コウラク",
"meaning": "outing, excursion, pleasure trip, going on a picnic"
},
{
"example": "猿楽",
"reading": "サルガク",
"meaning": "sarugaku (form of theatre popular in Japan during the 11th to 14th centuries), noh, fooling around"
}
],
"kunyomiExamples": [
{
"example": "楽しい",
"reading": "たのしい",
"meaning": "enjoyable, fun, pleasant, happy, delightful"
},
{
"example": "楽しい思い出",
"reading": "たのしいおもいで",
"meaning": "happy memory, sweet memory"
},
{
"example": "楽しむ",
"reading": "たのしむ",
"meaning": "to enjoy (oneself)"
}
],
"radical": {
"symbol": "木",
"meaning": "tree"
},
"parts": [
"冫",
"木",
"白"
],
"strokeOrderDiagramUri": "http://classic.jisho.org/static/images/stroke_diagrams/27005_frames.png",
"strokeOrderSvgUri": "http://d1w6u4xc3l95km.cloudfront.net/kanji-2015-03/0697d.svg",
"strokeOrderGifUri": "https://raw.githubusercontent.com/mistval/kanji_images/master/gifs/697d.gif",
"uri": "http://jisho.org/search/%E6%A5%BD%23kanji"
}
}

View File

@ -0,0 +1,7 @@
{
"query": "極上",
"expectedResult": {
"query": "極上",
"found": false
}
}

View File

@ -0,0 +1,52 @@
{
"query": "贄",
"expectedResult": {
"query": "贄",
"found": true,
"strokeCount": 18,
"meaning": "offering, sacrifice",
"kunyomi": [
"にえ"
],
"onyomi": [
"シ"
],
"onyomiExamples": [],
"kunyomiExamples": [
{
"example": "贄",
"reading": "にえ",
"meaning": "offering (to the gods, emperor, etc.), gift, sacrifice"
},
{
"example": "早贄",
"reading": "はやにえ",
"meaning": "butcher-bird prey impaled on twigs, thorns, etc. for later consumption, first offering of the season"
},
{
"example": "百舌の早贄",
"reading": "もずのはやにえ",
"meaning": "butcher-bird prey impaled on twigs, thorns, etc. for later consumption"
}
],
"radical": {
"symbol": "貝",
"meaning": "shell"
},
"parts": [
"ハ",
"",
"九",
"亠",
"十",
"目",
"立",
"貝",
"辛"
],
"strokeOrderDiagramUri": "http://classic.jisho.org/static/images/stroke_diagrams/36100_frames.png",
"strokeOrderSvgUri": "http://d1w6u4xc3l95km.cloudfront.net/kanji-2015-03/08d04.svg",
"strokeOrderGifUri": "https://raw.githubusercontent.com/mistval/kanji_images/master/gifs/8d04.gif",
"uri": "http://jisho.org/search/%E8%B4%84%23kanji"
}
}

View File

@ -0,0 +1,7 @@
{
"query": "ネガティブ",
"expectedResult": {
"query": "ネガティブ",
"found": false
}
}

View File

@ -0,0 +1,7 @@
{
"query": "wegmwrlgkrgmg",
"expectedResult": {
"query": "wegmwrlgkrgmg",
"found": false
}
}

View File

@ -0,0 +1,78 @@
{
"query": "水",
"expectedResult": {
"query": "水",
"found": true,
"taughtIn": "grade 1",
"jlptLevel": "N5",
"newspaperFrequencyRank": "223",
"strokeCount": 4,
"meaning": "water",
"kunyomi": [
"みず",
"みず-"
],
"onyomi": [
"スイ"
],
"onyomiExamples": [
{
"example": "水",
"reading": "スイ",
"meaning": "Wednesday, shaved ice (served with flavored syrup), water (fifth of the five elements)"
},
{
"example": "水位",
"reading": "スイイ",
"meaning": "water level"
},
{
"example": "用水",
"reading": "ヨウスイ",
"meaning": "irrigation water, water for fire, city water, cistern water"
},
{
"example": "浄水",
"reading": "ジョウスイ",
"meaning": "clean water"
}
],
"kunyomiExamples": [
{
"example": "水",
"reading": "みず",
"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": "drinking water, potable water"
},
{
"example": "呼び水",
"reading": "よびみず",
"meaning": "pump-priming, rousing, stimulation"
}
],
"radical": {
"symbol": "水",
"forms": [
"氵",
"氺"
],
"meaning": "water"
},
"parts": [
"水"
],
"strokeOrderDiagramUri": "http://classic.jisho.org/static/images/stroke_diagrams/27700_frames.png",
"strokeOrderSvgUri": "http://d1w6u4xc3l95km.cloudfront.net/kanji-2015-03/06c34.svg",
"strokeOrderGifUri": "https://raw.githubusercontent.com/mistval/kanji_images/master/gifs/6c34.gif",
"uri": "http://jisho.org/search/%E6%B0%B4%23kanji"
}
}

View File

@ -0,0 +1,100 @@
{
"query": "車",
"expectedResult": {
"found": true,
"query": "車",
"uri": "https://jisho.org/word/%E8%BB%8A",
"tags": [
"Common word",
"JLPT N5",
"Wanikani level 4"
],
"meanings": [
{
"seeAlsoTerms": [],
"sentences": [
{
"english": "You cannot be too careful when you drive a car.",
"japanese": "車を運転する時はいくら注意してもしすぎることはない。",
"pieces": [
{
"lifted": "くるま",
"unlifted": "車"
},
{
"lifted": "",
"unlifted": "を"
},
{
"lifted": "うんてん",
"unlifted": "運転"
},
{
"lifted": "",
"unlifted": "する"
},
{
"lifted": "とき",
"unlifted": "時"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "",
"unlifted": "いくら"
},
{
"lifted": "ちゅうい",
"unlifted": "注意"
},
{
"lifted": "",
"unlifted": "して"
},
{
"lifted": "",
"unlifted": "も"
},
{
"lifted": "",
"unlifted": "しすぎる"
},
{
"lifted": "",
"unlifted": "こと"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "",
"unlifted": "ない"
}
]
}
],
"definition": "car; automobile; vehicle",
"supplemental": [],
"definitionAbstract": "",
"tags": [
"noun"
]
},
{
"seeAlsoTerms": [],
"sentences": [],
"definition": "wheel",
"supplemental": [],
"definitionAbstract": "",
"tags": [
"noun"
]
}
],
"otherForms": [],
"notes": []
}
}

View File

@ -0,0 +1,40 @@
{
"query": "日本人",
"expectedResult": {
"found": true,
"query": "日本人",
"uri": "https://jisho.org/word/%E6%97%A5%E6%9C%AC%E4%BA%BA",
"tags": [
"Common word"
],
"meanings": [
{
"seeAlsoTerms": [],
"sentences": [],
"definition": "Japanese person; Japanese people",
"supplemental": [],
"definitionAbstract": "",
"tags": [
"noun"
]
},
{
"seeAlsoTerms": [],
"sentences": [],
"definition": "Japanese people",
"supplemental": [],
"definitionAbstract": "The Japanese people are a nationality originating in the Japanese archipelago and are the predominant ethnic group of Japan. Worldwide, approximately 130 million people are of Japanese descent; of these, approximately 127 million are residents of Japan. People of Japanese ancestry who live in other countries are referred to as nikkeijin . The term ethnic Japanese may also be used in some contexts to refer to a locus of ethnic groups including the Yamato, Ainu and Ryukyuan people.",
"tags": [
"wikipedia definition"
]
}
],
"otherForms": [
{
"kanji": "日本人",
"kana": "にっぽんじん"
}
],
"notes": []
}
}

View File

@ -0,0 +1,135 @@
{
"query": "皆",
"expectedResult": {
"found": true,
"query": "皆",
"uri": "https://jisho.org/word/%E7%9A%86",
"tags": [
"Common word",
"JLPT N5"
],
"meanings": [
{
"seeAlsoTerms": [],
"sentences": [
{
"english": "The people which were here have all gone.",
"japanese": "ここにいた人々はみんな行ってしまった。",
"pieces": [
{
"lifted": "",
"unlifted": "ここ"
},
{
"lifted": "",
"unlifted": "に"
},
{
"lifted": "",
"unlifted": "いた"
},
{
"lifted": "ひとびと",
"unlifted": "人々"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "",
"unlifted": "みんな"
},
{
"lifted": "い",
"unlifted": "行って"
},
{
"lifted": "",
"unlifted": "しまった"
}
]
}
],
"definition": "all; everyone; everybody",
"supplemental": [
"Usually written using kana alone"
],
"definitionAbstract": "",
"tags": [
"adverb",
"noun"
]
},
{
"seeAlsoTerms": [],
"sentences": [
{
"english": "All the dinner had been eaten before he came.",
"japanese": "ごちそうはみんな彼が来ないうちに食べられてしまった。",
"pieces": [
{
"lifted": "",
"unlifted": "ごちそう"
},
{
"lifted": "",
"unlifted": "は"
},
{
"lifted": "",
"unlifted": "みんな"
},
{
"lifted": "かれ",
"unlifted": "彼"
},
{
"lifted": "",
"unlifted": "が"
},
{
"lifted": "らい",
"unlifted": "来"
},
{
"lifted": "",
"unlifted": "ないうちに"
},
{
"lifted": "た",
"unlifted": "食べられて"
},
{
"lifted": "",
"unlifted": "しまった"
}
]
}
],
"definition": "everything",
"supplemental": [
"Usually written using kana alone"
],
"definitionAbstract": "",
"tags": [
"adverb",
"noun"
]
}
],
"otherForms": [
{
"kanji": "皆んな",
"kana": "みんな"
},
{
"kanji": "皆",
"kana": "みな"
}
],
"notes": [
"皆んな: Irregular okurigana usage."
]
}
}

View File

@ -0,0 +1,69 @@
{
"query": "ネガティブ",
"expectedResult": {
"found": true,
"query": "ネガティブ",
"uri": "https://jisho.org/word/%E3%83%8D%E3%82%AC%E3%83%86%E3%82%A3%E3%83%96",
"tags": [
"Common word"
],
"meanings": [
{
"seeAlsoTerms": [],
"sentences": [],
"definition": "negative (e.g. thinking)",
"supplemental": [
"Antonym: ポジティブ"
],
"definitionAbstract": "",
"tags": [
"na-adjective"
]
},
{
"seeAlsoTerms": [],
"sentences": [],
"definition": "negative (photography)",
"supplemental": [],
"definitionAbstract": "",
"tags": [
"noun"
]
},
{
"seeAlsoTerms": [
"陰極"
],
"sentences": [],
"definition": "negative (electrical polarity)",
"supplemental": [],
"definitionAbstract": "",
"tags": [
"noun"
]
},
{
"seeAlsoTerms": [],
"sentences": [],
"definition": "Negative (Finnish band)",
"supplemental": [],
"definitionAbstract": "Negative is a Finnish glam rock band founded at the end of 1997. Members of Negative cite musical influence such as Guns N' Roses, Queen, and Hanoi Rocks. The band itself labels the music as ”emotional rockn roll”.",
"tags": [
"wikipedia definition"
]
}
],
"otherForms": [
{
"kanji": "ネガティヴ"
},
{
"kanji": "ネガチブ"
},
{
"kanji": "ネガチィブ"
}
],
"notes": []
}
}

View File

@ -0,0 +1,7 @@
{
"query": "grlgmregmneriireg",
"expectedResult": {
"query": "grlgmregmneriireg",
"found": false
}
}

View File

@ -0,0 +1,60 @@
import 'dart:io' as io;
import 'package:path/path.dart' as path;
import 'dart:convert';
import 'package:unofficial_jisho_api/unofficial_jisho_api.dart';
import 'package:test/test.dart';
final jisho = API();
List<String> getFilePaths(String dirname) {
final currentdir = io.Directory.current.path;
final filenames = io.Directory(path.join(currentdir, 'test', dirname)).listSync();
return filenames.map((filename) => path.join(currentdir, 'test', dirname, filename.path)).toList();
}
void runTestCases(testCaseFiles, apiFunction) async {
for (var testCount = 0; testCount < testCaseFiles.length; testCount++) {
final file = await io.File(testCaseFiles[testCount]).readAsString();
final testCase = jsonDecode(file);
test('Test ${testCount}', () async {
switch(apiFunction) {
case 'searchForKanji': {
final result = await jisho.searchForKanji(testCase.query);
expect(result, testCase.expectedResult);
break;
}
case 'searchForExamples': {
final result = await jisho.searchForExamples(testCase.query);
expect(result, testCase.expectedResult);
break;
}
case 'scrapeForPhrase': {
final result = await jisho.scrapeForPhrase(testCase.query);
expect(result, testCase.expectedResult);
break;
}
throw 'No API function provided';
}
});
}
}
void main() {
group('Kanji test cases', () {
final filePaths = getFilePaths('kanji_test_cases');
runTestCases(filePaths, 'searchForKanji');
});
group('Example test cases', () {
final filePaths = getFilePaths('example_test_cases');
runTestCases(filePaths, 'searchForExamples');
});
group('Phrase scrape test cases', () {
final filePaths = getFilePaths('phrase_scrape_test_cases');
runTestCases(filePaths, 'scrapeForPhrase');
});
}