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?

closed as off-topic by Henri Menke, Raaja, TeXnician, user156344, Phelype Oleinik May 6 at 13:01

  • This question does not fall within the scope of TeX, LaTeX or related typesetting systems as defined in the help center.
If this question can be reworded to fit the rules in the help center, please edit the question.

  • where do you have JSON.lua from? – Ulrike Fischer May 6 at 8:30
  • @UlrikeFischer It is inside the same directory from where the above code is running. – Amanda May 6 at 8:35
  • This doesn't help me to test your code, I can't access your directory. – Ulrike Fischer May 6 at 8:37
  • @UlrikeFischer Sorry. I downloaded it from regex.info/blog/lua/json – Amanda May 6 at 8:41
  • 4
    I'm voting to close this question as off-topic because the problem is caused by a simple typographic error. – Henri Menke May 6 at 9:18
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 }
  • Works fine! What is the error with the code I have given in the question? – Amanda May 6 at 9: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 6 at 10:34
  • @Amanda \newcommand*\apply[1]{\directlua{tex.print(#1)}} – Henri Menke May 6 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 7 at 13:56

Not the answer you're looking for? Browse other questions tagged or ask your own question.