#8389·mealie

[BUG] - Schema.org JSON-LD recipeIngredient ignores unit abbreviation and runs food and note together

Author: purpleturtle1988Created Sep 13, 2026Updated Sep 13, 2026

First Check

  • This is not a feature request.
  • I added a very descriptive title to this issue (title field is above this).
  • I used the GitHub search to find a similar issue and didn't find it.
  • I searched the Mealie documentation, with the integrated search.
  • I already read the docs and didn't find an answer.
  • This issue can be replicated on the demo site (https://demo.mealie.io/).

What is the issue you are experiencing?

The Schema.org JSON-LD that Mealie injects into the recipe page builds each recipeIngredient string in a way that other apps can't split back into food, amount and note. The most visible case is the documented Bring! recipe action: Bring parses these strings and ends up putting units and notes into the item name.

I'm using exactly the setup from the docs: a recipe action of type "link" with the URL given there, https://api.getbring.com/rest/bringrecipes/deeplink?url=${url}&source=web. Nothing custom in between.

The strings are built here: https://github.com/mealie-recipes/mealie/blob/8d0cebfd5eafe13ef53f7c02b7822ecf9ec232c8/mealie/routes/spa/__init__.py#L132-L144

Three things go wrong:

  1. The unit's full name is always used, even when "use abbreviation" is enabled on the unit. Mealie sends 2.5 Deziliter Milch instead of 2.5 dl Milch. Bring doesn't recognise "Deziliter" as a unit and turns it into the item name "Deziliter Milch".
  2. There is no separator between food and note. 200 g Lauch in feinen Streifen can't be split, so the note becomes part of the item name ("Lauch in feinen Streifen").
  3. Quantities are raw floats (100.0, 2.0), and the unit's fraction/decimal setting is ignored. Bring copies the number as it is, so "2 Eier" shows up as "Ei 2.0" and "1 Butterkuchenteig" as "1.0".

The recipe page itself renders all of this correctly (2.5 dl Milch, note shown separately), because the frontend and RecipeIngredientBase._format_display() respect use_abbreviation and fraction. Only the JSON-LD path builds its own string.

Result in Bring (from Bring's public parser, https://api.getbring.com/rest/bringrecipes/parser?url=<recipe url>), for a German recipe with units set to use abbreviations:

Mealie ingredient JSON-LD today Bring item name Bring spec
2.5 dl Milch 2.5 Deziliter Milch Deziliter Milch 2.5
200 g Lauch, note "in feinen Streifen" 200.0 Gramm Lauch in feinen Streifen Lauch in feinen Streifen 200.0 Gramm
2 Ei 2.0 Ei Ei 2.0

I served the same ingredients from a static test page using the unit abbreviation, a comma before the note and no trailing .0, and Bring parsed every line cleanly:

JSON-LD Bring item name Bring spec
2.5 dl Milch Milch 2.5 dl
200 g Lauch, in feinen Streifen Lauch 200 g, in feinen Streifen
2 Ei Ei 2
1 EL Olivenöl, kaltgepresst Olivenöl 1 EL, kaltgepresst

Wrapping the note in parentheses (200 g Lauch (in feinen Streifen)) gave the same result.

Suggested fix: build the JSON-LD string from the existing display helpers instead of raw fields, i.e. _format_quantity_for_display(), _format_unit_for_display() and _format_food_for_display(), then append the note after ", ". One detail: when a unit has fraction enabled, the display helper returns unicode fractions like 2 ¹/₂, which parsers probably won't read. A plain decimal (2.5) is likely the safer choice for JSON-LD in every case. Whole numbers should be written without a trailing .0 (2 Ei, not 2.0 Ei). _format_quantity_for_display() already does this for decimal units, so reusing it covers this case too.

Related but separate: #8148 (times not in ISO 8601, Bring shows "1 hour" as 1 minute) and #7881 (recipeYield is 0.0 when only servings are set).

Steps to Reproduce

  1. Add the Bring! recipe action as described in the docs (type "link", URL https://api.getbring.com/rest/bringrecipes/deeplink?url=${url}&source=web).
  2. Under Data Management > Units, make sure a unit (e.g. Deziliter, abbreviation dl) has "use abbreviation" enabled.
  3. Create a public recipe with structured ingredients, e.g. 2.5 dl Milch, and 200 g Lauch with the note "in feinen Streifen".
  4. Click the Bring! action, or open the recipe page and look at the <script type="application/ld+json"> block, or run curl -s "https://api.getbring.com/rest/bringrecipes/parser?url=<recipe url>".
  5. Note that recipeIngredient contains 2.5 Deziliter Milch and 200.0 Gramm Lauch in feinen Streifen, and that Bring returns "Deziliter Milch" and "Lauch in feinen Streifen" as item names.

Please provide relevant logs

No errors are logged, this is an output formatting problem. Excerpt of the JSON-LD from the recipe page:

json
"recipeIngredient": [
  "1.0 Butterkuchenteig rund ausgewallt, ca. 32 cm Ø",
  "100.0 Gramm Speckwürfeli ",
  "200.0 Gramm Lauch in feinen Streifen",
  "300.0 Gramm Gruyère AOP rezent, grob geraffelt",
  "2.0 Ei ",
  "2.5 Deziliter Milch ",
  "1.8 Deziliter Halbrahm ",
  "Pfeffer "
]

Mealie Version

v3.25.0 (the code above is unchanged on mealie-next as of 8d0cebf)

Deployment

Docker (Synology)

Additional Deployment Details

No response