【问题标题】:Deserializing an object with other objects in it反序列化包含其他对象的对象
【发布时间】:2018-03-20 00:16:44
【问题描述】:

我正在制作一个在命令行上玩的两人棋局。我为每种类型的棋子和棋盘课程开设了一堂课。棋盘类如下所示:

class Board 
  attr_accessor :board, :choice
  def initialize
    @board = Array.new(8){Array.new(8," ")}
    @choice = choice 
  end 
end

我的其他课程如下所示:

class Bishop
  attr_accessor :x_position, :y_position, :piece, :color, :counter, :moves
  def initialize(position,boolean) 
    @x_position = position[0]
    @y_position = position[1]
    @piece = boolean ? "♝" : "♗"
    @color = boolean ? "white" : "black"
    @counter = 0
    @moves = [[+1,-1],
    [+1,+1],
    [-1,+1],
    [-1,-1]]
  end 

我像这样将我的棋子添加到板上:

@board[0][0] = Rook.new([0,0],false)

这些是我序列化和反序列化数据的方法:

def to_json
  JSON.generate({board: @board})
end

def save_game(string) 
  File.open("saved.json", "w") do |game_file|
    game_file.write(string)
  end
end

def load_game
  game_file = File.read("saved.json")
  data = JSON.parse(game_file)
  @board = data["board"]
end 

保存后保存的.json文件如下:

{"board":[[" ","#<Knight:0x00000000e4fc28>","#<Bishop:0x00000000e4fa20>","#<Queen:0x00000000e4f890>","#<King:0x00000000e4f610>","#<Bishop:0x00000000e4f3e0>","#<Knight:0x00000000e4f278>","#<Rook:0x00000000e4e1c0>"],[" "," "," "," "," "," "," "," "],[" "," "," "," "," "," "," "," "],[" "," "," "," "," "," "," "," "],[" "," "," "," "," "," "," "," "],[" "," "," "," "," "," "," "," "],[" "," "," "," "," "," "," "," "],["#<Rook:0x00000000e4fd90>","#<Knight:0x00000000e4ed78>","#<Bishop:0x00000000e4eb70>","#<Queen:0x00000000e4ea08>","#<King:0x00000000e4e7b0>","#<Bishop:0x00000000e4e580>","#<Knight:0x00000000e4e3f0>"," "]]}

当我尝试加载数据时,显示板的方法抛出此错误:

 0    1    2    3    4    5    6    7
 +----+----+----+----+----+----+----+----+
0|    /home/jacob/Desktop/chess/board.rb:30:in `block (2 levels) in display': undefined method `piece' for "#<Knight:0x00000000e4fc28>":String (NoMethodError)
    from /home/jacob/Desktop/chess/board.rb:27:in `each'
    from /home/jacob/Desktop/chess/board.rb:27:in `each_with_index'
    from /home/jacob/Desktop/chess/board.rb:27:in `block in display'
    from /home/jacob/Desktop/chess/board.rb:20:in `each'
    from /home/jacob/Desktop/chess/board.rb:20:in `each_with_index'

看来我的问题是对象以字符串形式返回?

我的展示方式:

 def display
    axis = 0
    print "   0    1    2    3    4    5    6    7"
    @board.each_with_index do |row,index|
      print "\n"
      @draw = " +----+----+----+----+----+----+----+----+"
      puts @draw
      print axis
      axis +=1
      if index.even?
        row.each_with_index do|column,i|
          if i.odd?
            if column != " "
              print "|"+" #{column.piece}  ".bruno
            else  print "|"+" #{column}  ".bruno
            end
          else
            if column != " "
              print "|"+" #{column.piece}  "
            else  print "|"+" #{column}  "
            end
          end 
        end
      else
        row.each_with_index do|column,j|
          if j.even?
            if column != " "
              print "|"+" #{column.piece}  ".bruno
            else  print "|"+" #{column}  ".bruno
            end
          else   
            if column != " "
              print "|"+" #{column.piece}  "
            else  print "|"+" #{column}  "
            end
          end
        end
      end
      print "|"
    end 
    print "\n"
    print @draw
  end

【问题讨论】:

  • 哪个部分属于哪个文件?没有它,我们就无法跟踪回溯。在您显示的内容中没有任何地方调用piece,这是导致错误的原因。
  • Piece 是所有类型的 Piece 类中的一个实例。

标签: json ruby serialization deserialization


【解决方案1】:

不,问题是您的对象被保存为字符串。在这种情况下,反序列化工作正常。您必须明确指定游戏片段的 json 表示形式。像这样的:

class Rook
  def to_json(*)
    { name: 'rook', position: 'A1', status: 'in_game' }.to_json
  end
end

pieces = [Rook.new]
pieces.to_json # => "[{\"name\":\"rook\",\"position\":\"A1\",\"status\":\"in_game\"}]"
JSON.parse(pieces.to_json) # => [{"name"=>"rook", "position"=>"A1", "status"=>"in_game"}]

在反序列化时,您必须执行相反的操作。从解析 JSON 文件获得的普通 ruby​​ 哈希构造适当的游戏类。

或者,如果您实际上并不关心 JSON 并且只想创建 一些 形式的保存文件,那么 Marshal 是您最好的朋友。无需覆盖任何东西。零摩擦。

pieces = [Rook.new]
Marshal.dump(pieces) # => "\x04\b[\x06o:\tRook\x00" # write this to a file
# restore it later
Marshal.load("\x04\b[\x06o:\tRook\x00") # => [#<Rook:0x007fb50f825570>]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-01
    • 2015-06-11
    • 2021-10-05
    相关资源
    最近更新 更多