0

I am trying to read a JSON file and trying to display some of its content. But as I try this, I get an error saying attempt to call a nil value as also shown below.

enter image description here

I could not understand the reason for this. Here is the latex code I am trying to run as lualatex ty.tex

\documentclass{report}
\usepackage{luacode}
\begin{document}

% load json file
\begin{luacode}
function read(file)
    local handler = io.open(file, "rb")
    local content = handler:read("*all")
    handler:close()
    return content
end
JSON = (loadfile "JSON.lua")()
table = JSON:decode(read("sample.json"))
\end{luacode}

The name of the document is \directlua{tex.print(table['documentName'])} with ID as \directlua{tex.print(table['documentId'])} and mac-protocol-id as \directlua{tex.print(table['macProtocolID'])}

The name of the company is \directlua{tex.print(table['headerFooter']['header]['left'])}

\end{document}

Here is the file named sample.json that I am trying to read from the above code:

        {
        "documentName": "MTRD Report",
        "documentId": "D-FF/1",
        "documentGeneratedAt": "06-05-2019",
        "documentGeneratedBy": "admin@foo.com",
        "macProtocolID": "CV/1",
        "headerFooter": {
            "header": {
                "left": "AA, Head Office (CC, DD)",
                "right": "For Restricted Circulation Only"
            },
            "footer": {
                "left": "DFFF/1"
            }
        }
    }

What could be the reason for the error? What mistake am I making?

Amanda
  • 387

1 Answers1

2

I'm going to give a little sneak preview of what I am going to present at the TUG 2019 conference, namely a JSON parser implemented in LuaTeX in only about 60 lines of Lua code, thank to the LPEG library which is bundled with LuaTeX.

First of all let's see the usage:

\documentclass{report}
\usepackage{luacode}
% load json file
\begin{luacode}
local json = require("json")
local file = io.open("sample.json")
tab = json.parse(file:read("*all"))
file:close()
\end{luacode}

\begin{document}

The name of the document is \directlua{tex.print(tab['documentName'])} with ID
as \directlua{tex.print(tab['documentId'])} and mac-protocol-id as
\directlua{tex.print(tab['macProtocolID'])}

The name of the company is
\directlua{tex.print(tab['headerFooter']['header']['left'])}

\end{document}

Note that I replaced the variable table with tab because table is a builtin library of Lua which you don't want to overwrite.

Now for the Lua code. The 60 lines come from the fact that I generously spaced out the grammar for better readability. Save it as json.lua in the same directory as your document.

local lpeg = assert(require("lpeg"))
local C, Cf, Cg, Ct, P, R, S, V =
    lpeg.C, lpeg.Cf, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.R, lpeg.S, lpeg.V

-- number parsing
local digit    = R"09"
local dot      = P"."
local eE       = S"eE"
local sign     = S"+-"^-1
local mantissa = digit^1 * dot * digit^0 + dot * digit^1 + digit^1
local exponent = (eE * sign * digit^1)^-1
local real     = sign * mantissa * exponent / tonumber

-- optional whitespace
local ws = S" \t\n\r"^0

-- match a literal string surrounded by whitespace
local lit = function(str)
    return ws * P(str) * ws
end

-- match a literal string and synthesize an attribute
local attr = function(str,attr)
    return ws * P(str) / function() return attr end * ws
end

-- JSON grammar
local json = P{
    "object",

    value =
        V"null_value" +
        V"bool_value" +
        V"string_value" +
        V"real_value" +
        V"array" +
        V"object",

    null_value =
        attr("null", nil),

    bool_value =
        attr("true", true) + attr("false", false),

    string_value =
        ws * P'"' * C((P'\\"' + 1 - P'"')^0) * P'"' * ws,

    real_value =
        ws * real * ws,

    array =
        lit"[" * Ct((V"value" * lit","^-1)^0) * lit"]",

    member_pair =
        Cg(V"string_value" * lit":" * V"value") * lit","^-1,

    object =
        lit"{" * Cf(Ct"" * V"member_pair"^0, rawset) * lit"}"
}

return { parse = function(str) return assert(json:match(str)) end }
Henri Menke
  • 109,596
  • Works fine! What is the error with the code I have given in the question? – Amanda May 06 '19 at 09:13
  • Is there some way, I could avoid writing the statement \directlua{tex.print(tab['documentId'])} everytime? Could I shorten this command to something like \apply{tab['documentId']}? – Amanda May 06 '19 at 10:34
  • @Amanda \newcommand*\apply[1]{\directlua{tex.print(#1)}} – Henri Menke May 06 '19 at 10:50
  • I was trying your library code separately as a lua file and using lua interpreter but it fails with an error saying module 'lpeg' not found. Could you tell how could I install this dependency? – Amanda May 07 '19 at 13:56