recipe-importer is a lightweight Kotlin library for parsing JSON-LD recipe metadata from web pages. It extracts structured recipe data (ingredients, instructions, images, nutrition info, etc.) from any HTML containing ld+json script tags of type Recipe. Designed for both Kotlin/JVM projects and Android apps, it provides a clean, idiomatic API for integrating recipe data into your applications.
- Extract recipes from HTML
ld+jsonscripts. - Parse structured data including:
- Title, description, author
- Ingredients and instructions (supports nested steps)
- Prep, cook, and total time
- Yield/servings
- Nutrition info (calories, fat, protein, sugar)
- Images and videos
- Ratings and rating counts
- Safe handling of JSON arrays, objects, and primitives.
- Fully Kotlin idiomatic API.
- Compatible with Android and JVM projects.
- Minimal dependencies: Kotlinx Serialization and Jsoup.
Add JitPack repository:
repositories {
maven { url = uri("https://jitpack.io") }
}Add dependency:
dependencies {
implementation("com.github.seyone22:recipe-importer:1.0.2")
}import recipeimporter.parser.JsonLdExtractor
import kotlinx.serialization.json.JsonObject
val html: String = fetchHtmlFromUrl("https://example.com/recipe")
val recipeJson: JsonObject? = JsonLdExtractor.extractRecipeJsonLd(html)
if (recipeJson != null) {
println("JSON-LD extracted successfully!")
} else {
println("No recipe JSON-LD found in the HTML.")
}import recipeimporter.parser.RecipeParser
import recipeimporter.models.Recipe
val recipe: Recipe? = recipeJson?.let { RecipeParser.parseRecipe(it) }
recipe?.let {
println("Recipe Title: ${it.title}")
println("Ingredients: ${it.ingredients.joinToString()}")
println("Instructions: ${it.instructions.joinToString { step -> step.text }}")
}| Class | Description |
|---|---|
Recipe |
Main data class representing a recipe. Contains title, ingredients, instructions, nutrition info, images, etc. |
InstructionSection |
Represents sections of instructions; can contain multiple steps. |
NutritionInfo |
Represents nutrition details (calories, fat, protein, sugar, etc.) |
import recipeimporter.parser.JsonLdExtractor
import kotlinx.serialization.json.JsonObject
val html: String = "<html>...</html>"
val recipeJson: JsonObject? = JsonLdExtractor.extractRecipeJsonLd(html)import recipeimporter.parser.RecipeParser
recipeJson?.let {
val recipe = RecipeParser.parseRecipe(it)
println(recipe.title)
println(recipe.ingredients)
}import kotlinx.coroutines.*
import java.net.URL
suspend fun fetchHtmlAsync(url: String): String = withContext(Dispatchers.IO) {
URL(url).readText()
}
runBlocking {
val html = fetchHtmlAsync("https://example.com/recipe")
val json = JsonLdExtractor.extractRecipeJsonLd(html)
val recipe = json?.let { RecipeParser.parseRecipe(it) }
println(recipe?.title)
}recipe?.nutritionInfo?.let {
println("Calories: ${it.calories ?: "N/A"}")
println("Protein: ${it.protein ?: "N/A"}")
}val html = fetchHtmlFromUrl("https://example.com/recipe")
val jsonLd = JsonLdExtractor.extractRecipeJsonLd(html)
val recipe = jsonLd?.let { RecipeParser.parseRecipe(it) }
println("Recipe: ${recipe?.title}")
println("Ingredients: ${recipe?.ingredients?.joinToString()}")| Issue | Solution |
|---|---|
No recipe JSON-LD found |
Ensure the page contains <script type="application/ld+json"> of type Recipe. |
Malformed JSON-LD |
Validate the page's JSON-LD using a JSON validator. |
Nested steps not parsed correctly |
Make sure to use InstructionSection API to access nested instructions. |
Multiple JSON-LD recipe scripts |
The parser will by default select the first script. |
-
JsonLdExtractor
extractRecipeJsonLd(html: String): JsonObject?→ Extracts the first recipe JSON-LD.
-
RecipeParser
parseRecipe(json: JsonObject): Recipe→ Converts JSON-LD into aRecipeobject.
-
Models
Recipe,InstructionSection,NutritionInfo,Ingredient,Step.
We welcome contributions!
- Fork the repository.
- Create a new feature branch (
git checkout -b feature/your-feature). - Add your code and tests.
- Submit a Pull Request.
Guidelines:
- Follow Kotlin idioms.
- Include unit tests for new features or bug fixes.
- Update documentation as needed.
This project is licensed under the MIT License - see the LICENSE file for details.