如何使用Lua的json.encode保持列表顺序不被打乱?
解决Lua表JSON编码后顺序乱序的问题
问题根源
- Lua哈希表特性:你定义的
GAMES是带字符串键的Lua表,这类表本质是哈希表,Lua的哈希表遍历顺序和定义顺序无关,是不固定的。 - JSON规范限制:标准JSON对象的键值对是无序的,即使部分JSON解析器会保留编码顺序,但这属于实现细节,不能依赖。
解决方案
方案1:将哈希表转为有序数组(推荐,符合JSON规范)
把原有的键值对结构改成有序数组,每个元素包含游戏ID和对应数据,这样JSON编码后数组的顺序会严格保留。
Lua端处理:
-- 先按原表定义顺序列出所有游戏键 local game_order = { "777_Thimble", "777e_Thimble", "777_Thimblet", "777e_Thimbrle", "777_Thimbgle", "777e_Thimbfle", "777_Thimbled", "777e_Thimble2", "777e_Thidmble2", "777e_Tdhidmble2", "777e_Thicxdmble2", "777e_Thidmbxle2", "777e_Tchidmble2", "777e_dTchidmble2", "777e_Tdchidmble2", "777e_Tcdhidmble2" } -- 构建有序数组 local ordered_games = {} for _, key in ipairs(game_order) do table.insert(ordered_games, { game_id = key, game_info = GAMES[key] }) end -- 编码有序数组 local json_result = json.encode(ordered_games)
JS端处理:
拿到JSON后,可以直接遍历数组,或者转成Map来保留顺序:
const games = JSON.parse(json_result); // 直接遍历数组(顺序和Lua定义一致) games.forEach(item => { console.log(item.game_id, item.game_info); }); // 转成Map,方便按ID查询同时保留顺序 const gameMap = new Map(games.map(item => [item.game_id, item.game_info]));
方案2:使用支持自定义排序的JSON库
如果不想修改原表结构,可以用支持键排序的Lua JSON库(比如dkjson),通过自定义排序函数强制按指定顺序编码。
Lua端处理:
local dkjson = require("dkjson") -- 定义游戏键的顺序映射(数字越小越靠前) local game_key_rank = { ["777_Thimble"] = 1, ["777e_Thimble"] = 2, ["777_Thimblet"] = 3, ["777e_Thimbrle"] = 4, ["777_Thimbgle"] = 5, ["777e_Thimbfle"] = 6, ["777_Thimbled"] = 7, ["777e_Thimble2"] = 8, ["777e_Thidmble2"] = 9, ["777e_Tdhidmble2"] = 10, ["777e_Thicxdmble2"] = 11, ["777e_Thidmbxle2"] = 12, ["777e_Tchidmble2"] = 13, ["777e_dTchidmble2"] = 14, ["777e_Tdchidmble2"] = 15, ["777e_Tcdhidmble2"] = 16 } -- 定义游戏子字段的顺序映射 local field_key_rank = { ["game_name"] = 1, ["game_thumbnail"] = 2, ["1x_multiplier"] = 3, ["2x_multiplier"] = 4, ["first_bet"] = 5, ["second_bet"] = 6, ["third_bet"] = 7, ["four_bet"] = 8, ["five_bet"] = 9, ["min_attributable_bet_value"] = 10, ["max_attributable_bet_value"] = 11 } -- 自定义排序函数 local function sort_by_order(a, b) -- 优先按游戏键顺序排序 local rank_a = game_key_rank[a] local rank_b = game_key_rank[b] if rank_a and rank_b then return rank_a < rank_b end -- 再按子字段顺序排序 rank_a = field_key_rank[a] rank_b = field_key_rank[b] if rank_a and rank_b then return rank_a < rank_b end -- 其他情况按字符串默认排序 return a < b end -- 编码时传入排序函数 local json_result = dkjson.encode(GAMES, {sort_keys = sort_by_order})
注意事项
- 方案1是最稳妥的,因为JSON数组的顺序是规范明确保证的,所有解析器都遵守。
- 方案2依赖第三方库,且需要维护顺序映射表,后续新增游戏或字段时要同步更新映射,否则顺序会出错。
内容的提问来源于stack exchange,提问作者Mehmet Akgün
相关产品推荐
相关产品推荐

