我正在尝试读取一个JSON
文件并显示其中的部分内容。但是当我尝试这样做时,我收到一条错误消息,attempt to call a nil value
如下所示。
我无法理解其中的原因。这是我尝试运行的 latex 代码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}
sample.json
以下是我尝试从上面的代码中读取的文件名称:
{
"documentName": "MTRD Report",
"documentId": "D-FF/1",
"documentGeneratedAt": "06-05-2019",
"documentGeneratedBy": "[email protected]",
"macProtocolID": "CV/1",
"headerFooter": {
"header": {
"left": "AA, Head Office (CC, DD)",
"right": "For Restricted Circulation Only"
},
"footer": {
"left": "DFFF/1"
}
}
}
错误的原因可能是什么?我犯了什么错误?
答案1
我将对我将在 TUG 2019 会议上展示的内容进行一些预览,即在 LuaTeX 中实现的 JSON 解析器,仅用大约 60 行 Lua 代码,这要归功于与 LuaTeX 捆绑在一起的 LPEG 库。
首先我们来看看用法:
\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}
请注意,我用替换了变量table
,tab
因为table
它是 Lua 的内置库,您不想覆盖它。
现在来看看 Lua 代码。60 行代码是因为我慷慨地将语法分开,以提高可读性。将其保存json.lua
在与文档相同的目录中。
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 }