Lua的table转换json的算法实现

889 阅读2分钟

1 为什么要自己实现这个算法

因为lua是一个轻量级的脚本语言,而轻量也意味着好多标准库或功能压根就没有,需要 开发者自己去实现,包括Json相关的转换的库,官方也没有,想要用,要么引用第三方开源, 要么自己去实现。

2 实现示例

文件位置: utils/table.lua

local Table = {}

function Table:getInstance(obj)
  obj = obj or {}
  local data = obj
  setmetatable(data, self)
  self.__index = self

  return data
end

-- Get Table size
function Table:getLength()
  local size = 0
  for _ in pairs(self) do size = size + 1 end
  return size
end

-- Check the Data is Array.
function Table:isArray()
 for key, _ in pairs(self) do
   if (type(key) ~= 'number') then
     return false
   end
 end

 return true
end

return Table

文件位置: utils/json.lua

local Table = require('utils.table')
local Module = { }

local function formatField(isArray, key, value)
  if isArray then
    return string.format("%s", value)
  end
  return string.format('"%s":%s', key, value)
end

-- Convert table data to string.
function Module.encode(data, level)
  level = level or 0
  local result = ''
  local size = 0
  local symbol = ''
  local tableSize =Table:getInstance(data):getLength()
  local isArray = Table:getInstance(data):isArray()
  for index, value in pairs(data) do
    size = size + 1
    if (size < tableSize)  then
      symbol = ','
    else
      symbol = ''
    end
    local valueType = type(value)
    if (valueType == 'table') then
      result = result .. formatField(isArray, index, Module.encode(value, level + 1) .. symbol)
    elseif valueType == 'boolean' then
      local boolStr = 'true'
      if not value then
        boolStr = 'false'
      end
      result = result .. formatField(isArray, index, boolStr .. symbol)
    elseif valueType == 'number' then
      result = result .. formatField(isArray, index, string.format('%s', value) .. symbol)
    else
      result = result .. formatField(isArray, index, string.format('"%s"', value) .. symbol)
    end
  end
  local leftSymbol = '{'
  local rightSymbol = '}'
  if isArray then
    leftSymbol = '['
    rightSymbol = ']'
  end
  return string.format("%s%s%s", leftSymbol, result, rightSymbol)
end

return Module

3 使用测试

3.1 使用测试

local Json = require('utils.json')
local testTable = {
  str = 'string',
  number = {1, 2, 3, 4},
  bool = true,
  collectStr = {
    foo = "foo value",
    bar = "bar str"
  },
  collectNumber = {
    foo = {1, 2, 3, {4, 5, 6}},
    bar = {{7, 8, 9}, 10 }
  },
  collectBool = {
    true,
    false,
    true
  },
  mix = {
    "str",
    10,
    false,
    table = {
      1, 2, 3, 4, {'foo', 'bar'}, false,
    },
  }
}

print(Json.encode(testTable))

3.2 title="输出结果"

{
  "str": "string",
  "number": [
    1,
    2,
    3,
    4
  ],
  "bool": true,
  "collectNumber": {
    "bar": [
      [
        7,
        8,
        9
      ],
      10
    ],
    "foo": [
      1,
      2,
      3,
      [
        4,
        5,
        6
      ]
    ]
  },
  "collectBool": [
    true,
    false,
    true
  ],
  "mix": {
    "1": "str",
    "2": 10,
    "3": false,
    "table": [
      1,
      2,
      3,
      4,
      [
        "foo",
        "bar"
      ],
      false
    ]
  },
  "collectStr": {
    "bar": "bar str",
    "foo": "foo value"
  }
}