Преобразование данных Lua в JSON

Этот аддон EPGP World of Warcraft создает файл базы данных epgp.lua.

Я написал плагин для преобразования данных Lua в объект JSON для отображения на веб-сайте гильдии. Это работало в более старых версиях аддона, но теперь у меня возникли проблемы с попыткой заставить его правильно преобразовать файл. Вот два фрагмента кода, демонстрирующие проблему преобразования — см. эту демонстрацию.

Первый отлично работает при формировании вложенного массива:

["roster_info"] = {
    {
        "Agantica", -- [1]
        "ROGUE", -- [2]
        "09/03-2013", -- [3]
    }, -- [1]
    {
        "Intikamim", -- [1]
        "PALADIN", -- [2]
        "17/02-2013", -- [3]
    }, -- [2]
},

становится

"roster_info" : [
    [
        "Agantica",
        "ROGUE",
        "09/03-2013"
    ],
    [
        "Intikamim",
        "PALADIN",
        "17/02-2013"
    ]
]

Но замена строки видит этот следующий фрагмент как вложенный массив, хотя он должен быть объектом внутри массива:

["bonus_loot_log"] = {
    {
        ["player"] = "Magebox",
        ["timestamp"] = "2013-03-07 13:44:00",
        ["coinsLeft"] = "-1",
        ["reward"] = "|cffa335ee|Hitem:86815:0:0:0:0:0:0:632235520:90:0:445|h[Attenuating Bracers]|h|r",
    }, -- [1]
            {
        ["player"] = "Lîutasila",
        ["coinsLeft"] = "-1",
        ["timestamp"] = "2013-03-07 13:47:00",
    }, -- [2]
},

становится

"bonus_loot_log" : [
    [
        "player" : "Magebox",
        "timestamp" : "2013-03-07 13:44:00",
        "coinsLeft" : "-1",
        "reward" : "|cffa335ee|Hitem:86815:0:0:0:0:0:0:632235520:90:0:445|h[Attenuating Bracers]|h|r"
    ],
    [
        "player": "Lîutasila",
        "coinsLeft": "-1",
        "timestamp": "2013-03-07 13:47:00"
    ]
]

Вот скрипт преобразования строк, который работает только с первым фрагментом.

lua_string
    .replace(/\[(.*)\]\s\=\s/g,'$1:')     // change equal to colon & remove outer brackets
    .replace(/[\t\r\n]/g,'')              // remove tabs & returns
    .replace(/\}\,\s--\s\[\d+\]\}/g,']]') // replace sets ending with a comment with square brackets
    .replace(/\,\s--\s\[\d+\]/g,',')      // remove close subgroup and comment
    .replace(/,(\}|\])/g,'$1')            // remove trailing comma
    .replace(/\}\,\{/g,'],[')             // replace curly bracket set with square brackets
    .replace(/\{\{/g,'[[')                // change double curlies to square brackets
    .replace(/EPGP_DB\s\=/,'');

Итак, мне нужна помощь в том, чтобы заставить Lua правильно конвертировать массив объектов (второй пример).


person Mottie    schedule 27.04.2013    source источник
comment
Как создается epgp.lua? Если это код lua, генерирующий этот вывод, вы можете отредактировать этот код и использовать библиотеку/модуль LuaJSON.   -  person hjpotter92    schedule 27.04.2013
comment
Он генерируется аддоном, когда вы выходите из World of Warcraft. Все, что вам нужно сделать, это загрузить файл необработанных данных на свой сайт.   -  person Mottie    schedule 27.04.2013
comment
Это из-за ваших строк replace sets ending with a comment with square brackets и change double curlies to square brackets. Двойные кудри не обязательно означают массив внутри массива. Объект внутри массива также является двойным кудри в Lua.   -  person Egor Skriptunoff    schedule 27.04.2013
comment
@EgorSkriptunoff, не могли бы вы обновить демо с тем, что вы описываете. Проблема, с которой я столкнулся, заключается в том, чтобы отличить объект от массива внутри массива, или, может быть, есть лучший метод, о котором я не подумал?   -  person Mottie    schedule 28.04.2013


Ответы (2)


Как правило, вы не можете преобразовать любую таблицу Lua в данные JSON, просто используя строковые операции. Проблема в том, что в то время как Lua использует таблицы как для массивов, так и для словарей, JSON нуждается в двух разных типах. Есть и другие синтаксические различия.

Лучше всего это решает модуль, который преобразует представление Lua в JSON. Просмотрите вики Lua по модулям JSON и найдите модуль Lua для преобразования Lua в JSON. Существует несколько модулей, некоторые из которых представляют собой чистый Lua, что является хорошим выбором для встраивания в WoW. Они правильно определяют, представляет ли таблица массив или словарь, и выводят соответствующий JSON.

person Michal Kottman    schedule 28.04.2013
comment
+1 за толчок в правильном направлении. Если потребителю данных нужен JSON, но у вас есть таблица Lua, правильным ответом будет создание JSON в первую очередь из кода Lua, а не попытка замены текста, которая может быть успешной только при использовании полного синтаксического анализатора Lua. Что на самом деле сводится к тому, чтобы заставить Lua записывать вывод JSON в первую очередь, и это решенная проблема. - person RBerteig; 30.04.2013

person    schedule
comment
+1 Хороший ответ, но, к сожалению, он работает в webkit, но не в Firefox: jsfiddle.net/Mottie/MfncJ/ 4 (используя полный файл epgp.lua) — возможно, Firefox не поддерживает совпадающие группы захвата? - person Mottie; 28.04.2013
comment
@Mottie — эта строка слишком длинная для операций с регулярными выражениями. - person Egor Skriptunoff; 28.04.2013
comment
@Mottie - Или слишком долго для анализа JSON. - person Egor Skriptunoff; 28.04.2013
comment
@Mottie - ИМО, мой код правильный. Проблема на стороне JavaScript. Я не знаю, как это решить. Можно ли переписать конвертер Lua->JSON на Lua вместо JavaScript? - person Egor Skriptunoff; 28.04.2013
comment
Я не думаю, что это правильное решение для этой проблемы. Если вы хотите преобразовать данные Lua в JSON, вы должны использовать один из доступных модулей Lua, которые выполняют это, и не полагаться на регулярное выражение для этого. - person Charles Sprayberry; 06.10.2017
comment
Кроме того, было бы полезно сопровождать фрагмент кода английским текстом — как минимум вводным. Не совсем чувствую, что ставлю против этого, но и не ставлю плюс. - person lindes; 25.08.2020
comment
@lindes - ответ устарел. В настоящее время я предпочитаю использовать полноценный конвертер (пример) вместо быстрого и грязного решения регулярных выражений. - person Egor Skriptunoff; 25.08.2020