この第1 版はLua 5.0 向けに書かれました。引き続き後続のバージョンでも大部分が関連しますが、いくつか違いがあります。
第4 版はLua 5.3 を対象としており、Amazon やその他の書店で購入できます。
本を購入することで、Luaプロジェクトのサポートにも協力できます。


12.1 – シリアル化

私たちはしばしばデータをシリアル化する必要があります。つまりデータをバイトまたは文字のストリームに変換し、ファイルを保存またはネットワーク接続経由で送信します。シリアル化されたデータをLua コードとして表現します。これにより、コードを実行すると、保存された値が読み取りプログラムに再構築されます。

通常、グローバル変数の値を復元する場合、チャンクは varname = <exp> のようになります。<exp> は値を作成するLuaコードです。varname は簡単な部分であるため、値を作成するコードの書き方を見ていきましょう。数値の場合、タスクは簡単です

    function serialize (o)
      if type(o) == "number" then
        io.write(o)
      else ...
    end
文字列値の場合、素朴なアプローチは次のようになります。
    if type(o) == "string" then
      io.write("'", o, "'")
ただし、文字列に特殊文字(引用符または改行など)が含まれている場合、結果のコードは有効なLuaプログラムではありません。ここでは、この問題を解決しようとして引用符を変更したくなるかもしれません
    if type(o) == "string" then
      io.write("[[", o, "]]")
やめてください!二重角括弧は手書きの文字列用であり、自動生成された文字列用ではありません。悪意のあるユーザーが " ]]..os.execute('rm *')..[[ " のようなものを保存するようにプログラムを誘導できた場合(たとえば、その文字列を住所として提供できる場合)、最終的なチャンクは次のようになります。
    varname = [[ ]]..os.execute('rm *')..[[ ]]
この「データ」を読み込もうとすると、不快な驚きがあります。

任意の文字列を安全に引用するために、標準の string ライブラリの format 関数が "%q" オプションを提供します。文字列を二重引用符で囲み、二重引用符、改行、文字列内の他の文字を適切にエスケープします。この機能を使用すると、serialize 関数は次のようになります。

    function serialize (o)
      if type(o) == "number" then
        io.write(o)
      elseif type(o) == "string" then
        io.write(string.format("%q", o))
      else ...
    end