【问题标题】:Convert JSON String to Lua Table?将 JSON 字符串转换为 Lua 表?
【发布时间】:2014-09-14 12:03:43
【问题描述】:

我需要在 Lua 中将 Json 字符串转换为表数据结构。我正在使用以下代码。

local json = require "json"

local t = { 
    ["name1"] = "value1",
    ["name2"] = { 1, false, true, 23.54, "a \021 string" },
    name3 = json.null
}

local encode = json.encode (t)
print (encode)  --> {"name1":"value1","name3":null,"name2":[1,false,true,23.54,"a \u0015 string"]}

local decode = json.decode( encode )

但是当我运行脚本时,出现以下错误,

    no field package.preload['json']
    no file '/usr/local/share/lua/5.2/json.lua'
    no file '/usr/local/share/lua/5.2/json/init.lua'
    no file '/usr/local/lib/lua/5.2/json.lua'
    no file '/usr/local/lib/lua/5.2/json/init.lua'
    no file './json.lua'
    no file '/usr/local/lib/lua/5.2/json.so'
    no file '/usr/local/lib/lua/5.2/loadall.so'
    no file './json.so'

那么如何将我的 json 字符串转换为 lua 表呢?

【问题讨论】:

  • 问题与编码无关。你必须在你的系统中安装一个“json”Lua 库。这可以像弹出“./json.lua”一样简单,或者您可以通过包管理器获取它。有多种选择。您使用的是哪一个,如何安装它以及在哪个操作系统上安装?
  • 你可能在关注LuaJSON

标签: json lua


【解决方案1】:

也许lua-cjson是你的朋友:

安装例如通过 luarocks:

$sudo luarocks install lua-cjson

然后在lua中:

local json = require('cjson')
local tab = json.decode(json_string)
json_string = json.encode(tab)

【讨论】:

    【解决方案2】:

    您可以使用json-lua。 json 的纯 lua 实现。首先使用 Luarocks 安装 json-lua。 luarocks install json-lua 。然后使用此代码:

    local json = require "json"
    
    local t = { 
        ["name1"] = "value1",
        ["name2"] = { 1, false, true, 23.54, "a \021 string" },
        name3 = json.null
    }
    
    local encode = json:encode (t)
    print (encode)  --> {"name1":"value1","name3":null,"name2":[1,false,true,23.54,"a \u0015 string"]}
    
    local decode = json:decode( encode )
    

    在带有 lua 5.1 的 win 7 64 位上测试和验证。 lua-cjson 很好,但它不是纯 lua 摇滚。所以,它的安装对你来说并不容易。

    【讨论】:

    • 可悲的是, json:decode 在我的情况下不起作用。在带有 Lua 5.2 的 Ubuntu 上使用有效的 json 字符串进行测试,它只返回 lua: /usr/share/lua/5.2/json/util.lua:55: bad argument #1 to 'pairs' (table expected, got string)
    • json-lua 有几种实现,有些需要点而不是冒号,所以json.decode(encode)。例如 Ubuntu 存储库中的情况就是这样。
    【解决方案3】:

    https://gist.github.com/tylerneylon/59f4bcf316be525b30ab

    我找到了一个纯lua脚本文件来解析json数据(只有一个文件)。

    local json = {}
    
    
    -- Internal functions.
    
    local function kind_of(obj)
      if type(obj) ~= 'table' then return type(obj) end
      local i = 1
      for _ in pairs(obj) do
        if obj[i] ~= nil then i = i + 1 else return 'table' end
      end
      if i == 1 then return 'table' else return 'array' end
    end
    
    local function escape_str(s)
      local in_char  = {'\\', '"', '/', '\b', '\f', '\n', '\r', '\t'}
      local out_char = {'\\', '"', '/',  'b',  'f',  'n',  'r',  't'}
      for i, c in ipairs(in_char) do
        s = s:gsub(c, '\\' .. out_char[i])
      end
      return s
    end
    
    -- Returns pos, did_find; there are two cases:
    -- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.
    -- 2. Delimiter not found: pos = pos after leading space;     did_find = false.
    -- This throws an error if err_if_missing is true and the delim is not found.
    local function skip_delim(str, pos, delim, err_if_missing)
      pos = pos + #str:match('^%s*', pos)
      if str:sub(pos, pos) ~= delim then
        if err_if_missing then
          error('Expected ' .. delim .. ' near position ' .. pos)
        end
        return pos, false
      end
      return pos + 1, true
    end
    
    -- Expects the given pos to be the first character after the opening quote.
    -- Returns val, pos; the returned pos is after the closing quote character.
    local function parse_str_val(str, pos, val)
      val = val or ''
      local early_end_error = 'End of input found while parsing string.'
      if pos > #str then error(early_end_error) end
      local c = str:sub(pos, pos)
      if c == '"'  then return val, pos + 1 end
      if c ~= '\\' then return parse_str_val(str, pos + 1, val .. c) end
      -- We must have a \ character.
      local esc_map = {b = '\b', f = '\f', n = '\n', r = '\r', t = '\t'}
      local nextc = str:sub(pos + 1, pos + 1)
      if not nextc then error(early_end_error) end
      return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))
    end
    
    -- Returns val, pos; the returned pos is after the number's final character.
    local function parse_num_val(str, pos)
      local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)
      local val = tonumber(num_str)
      if not val then error('Error parsing number at position ' .. pos .. '.') end
      return val, pos + #num_str
    end
    
    
    -- Public values and functions.
    
    function json.stringify(obj, as_key)
      local s = {}  -- We'll build the string as an array of strings to be concatenated.
      local kind = kind_of(obj)  -- This is 'array' if it's an array or type(obj) otherwise.
      if kind == 'array' then
        if as_key then error('Can\'t encode array as key.') end
        s[#s + 1] = '['
        for i, val in ipairs(obj) do
          if i > 1 then s[#s + 1] = ', ' end
          s[#s + 1] = json.stringify(val)
        end
        s[#s + 1] = ']'
      elseif kind == 'table' then
        if as_key then error('Can\'t encode table as key.') end
        s[#s + 1] = '{'
        for k, v in pairs(obj) do
          if #s > 1 then s[#s + 1] = ', ' end
          s[#s + 1] = json.stringify(k, true)
          s[#s + 1] = ':'
          s[#s + 1] = json.stringify(v)
        end
        s[#s + 1] = '}'
      elseif kind == 'string' then
        return '"' .. escape_str(obj) .. '"'
      elseif kind == 'number' then
        if as_key then return '"' .. tostring(obj) .. '"' end
        return tostring(obj)
      elseif kind == 'boolean' then
        return tostring(obj)
      elseif kind == 'nil' then
        return 'null'
      else
        error('Unjsonifiable type: ' .. kind .. '.')
      end
      return table.concat(s)
    end
    
    json.null = {}  -- This is a one-off table to represent the null value.
    
    function json.parse(str, pos, end_delim)
      pos = pos or 1
      if pos > #str then error('Reached unexpected end of input.') end
      local pos = pos + #str:match('^%s*', pos)  -- Skip whitespace.
      local first = str:sub(pos, pos)
      if first == '{' then  -- Parse an object.
        local obj, key, delim_found = {}, true, true
        pos = pos + 1
        while true do
          key, pos = json.parse(str, pos, '}')
          if key == nil then return obj, pos end
          if not delim_found then error('Comma missing between object items.') end
          pos = skip_delim(str, pos, ':', true)  -- true -> error if missing.
          obj[key], pos = json.parse(str, pos)
          pos, delim_found = skip_delim(str, pos, ',')
        end
      elseif first == '[' then  -- Parse an array.
        local arr, val, delim_found = {}, true, true
        pos = pos + 1
        while true do
          val, pos = json.parse(str, pos, ']')
          if val == nil then return arr, pos end
          if not delim_found then error('Comma missing between array items.') end
          arr[#arr + 1] = val
          pos, delim_found = skip_delim(str, pos, ',')
        end
      elseif first == '"' then  -- Parse a string.
        return parse_str_val(str, pos + 1)
      elseif first == '-' or first:match('%d') then  -- Parse a number.
        return parse_num_val(str, pos)
      elseif first == end_delim then  -- End of an object or array.
        return nil, pos + 1
      else  -- Parse true, false, or null.
        local literals = {['true'] = true, ['false'] = false, ['null'] = json.null}
        for lit_str, lit_val in pairs(literals) do
          local lit_end = pos + #lit_str - 1
          if str:sub(pos, lit_end) == lit_str then return lit_val, lit_end + 1 end
        end
        local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)
        error('Invalid json syntax starting at ' .. pos_info_str)
      end
    end
    
    return json
    

    【讨论】:

    • json.parse函数如何使用?
    猜你喜欢
    • 2013-12-23
    • 2017-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    • 2012-10-06
    • 1970-01-01
    相关资源
    最近更新 更多