[Tex/LaTex] Ways to parse JSON in LaTeX

jsonluatexparsing

I'm writing my recipes (food) in a small textfile in JSON. Are there any ways to parse this in LaTeX?
I know, that are lots of templates dealing with recipes, but I want to have my own style, which can be change very fast e.g. my mother is not interested in stuff like calories 🙂

Here is one simple example:

{
"recipe": {
    "title":"First recipe",
    "source":"My first cookbook",
    "carbs":"1 oz",
    "fat":"1 oz",
    "protein":"1 oz",
    "cal":"100 kcal",
    "ingredients": [
        {"item":"Eggs"},
        {"item":"Oil"},
        {"item":"Nuts"}
    ],
    "cooking": [
        {"step":"Mix eggs and oil"},
        {"step":"Add nuts"}
    ]
}
}

Best Answer

Although the question is about parsing JSON in LaTeX, since the OP wants to "have my own style, which can be change very fast", I'll give a ConTeXt solution for its simplicity.

ConTeXt already comes up with a parser for JSON. To use it, simply load

\usemodule[json]

Then, you can use the Lua function utilities.json.tolua to convert JSON string to Lua table and the Lua function utilities.json.tostring to convert a Lua table to a JSON string.

It is very simple to typeset Lua tables using ConTeXt Lua Document. Here is a complete example:

\usemodule[json]
\startluacode

  userdata = userdata or {}
  local json = utilities.json

  userdata.show_recipe = function(recipe)

  local lua_recipe  = json.tolua(recipe).recipe
  local ingredients = lua_recipe.ingredients
  local cooking     = lua_recipe.cooking

  context.subject(lua_recipe.title)

  local show_value = function(value)
    context.NC() context(value) 
    context.EQ() context(lua_recipe[value])
    context.NC() context.NR()
  end

  context.starttabulate()
    show_value("source")
    show_value("carbs")
    show_value("protein")
    show_value("cal")
  context.stoptabulate()

  context.subsubject("Ingredients")
  context.startitemize{"packed, intro"}
  for i = 1,#ingredients do
    context.startitem()
    context(ingredients[i].item)
    context.stopitem()
  end
  context.stopitemize()

  context.subsubject("Cooking")
  context.startitemize{"packed, intro"}
  for i = 1,#cooking do
    context.startitem()
    context(cooking[i].step)
    context.stopitem()
  end
  context.stopitemize()

  end
\stopluacode

Now you can simply define a TeX macro to pass its argument to the Lua function.

% Note that I use the braces around #1 to make the input
% syntax slightly simpler
\define[1]\Recipe
    {\ctxlua{userdata.show_recipe([==[{#1}]==])}}

Let's add some minimal styling to format the section heads. As with all ConTeXt documents, you can change the format by using appropriate \setup... command.

\setuphead[subject][style=\bfb]
\setuphead[subsubject][style=\bfa]

Finally, the main document

\starttext

\Recipe
    {
      "recipe": {
          "title":"First recipe",
          "source":"My first cookbook",
          "carbs":"1 oz",
          "fat":"1 oz",
          "protein":"1 oz",
          "cal":"100 kcal",
          "ingredients": [
              {"item":"Eggs"},
              {"item":"Oil"},
              {"item":"Nuts"}
          ],
          "cooking": [
              {"step":"Mix eggs and oil"},
              {"step":"Add nuts"}
          ]
      }
    } 

\stoptext

which gives

enter image description here