我该如何格式化一个JSON POST请求到我的Rails应用程序?

39

我的Rails应用程序中有一个运行完美的玩家类。可以在rails控制面板中创建、删除和更新玩家而不会出现任何问题。

我希望远程用户能够通过使用JSON请求来创建玩家,以便加入这个有趣的游戏。遵循自动生成的Rails注释上方我的create方法的建议:# POST /players.json,我开始向localhost:3000/players.json发送请求。

JSON内容:

{
    "player": {
    "name": "test",
    "room_id": 0,
    "skin_id": 1,
    "head_id": 2,
    "torso_id": 3,
    "legs_id": 4,
    "x_position": 5,
    "y_position": 6,
    "direction": 7,
    "action": "",
    "gender": "f"
    }
}

然而,我遇到了这个错误信息:

ActionController::ParameterMissing in PlayersController#create param not found: player

所以我的问题是:我应该如何结构化发送的JSON数据?

附加信息:

  • Ruby版本:2.0
  • Rails版本:4.0
  • 我已经尝试使用Postman发送请求

更新-Player Params

这是我控制器中的player params方法(按要求提供):

def player_params
    params.require(:player).permit(:name, :room_id, :skin_id, :head_id, :torso_id, :legs_id, :x_position, :y_position, :direction, :action, :gender)
end

更新2 - 玩家控制器

class PlayersController < ApplicationController
  before_action :set_player, only: [:show, :edit, :update, :destroy]
  skip_before_filter :verify_authenticity_token, :if => Proc.new { |c| c.request.format == 'application/json' }

  # GET /players
  # GET /players.json
  def index
    @players = Player.all
  end

  # GET /players/1
  # GET /players/1.json
  def show
  end

  # GET /players/new
  def new
    @player = Player.new
  end

  # GET /players/1/edit
  def edit
    @rooms = Room.all.map { |room| [room.name, room.id] }
  end

  # POST /players
  # POST /players.json
  def create
    @player = Player.new(player_params)

    respond_to do |format|
      if @player.save
        format.html { redirect_to @player, notice: 'Player was successfully created.' }
        format.json { render action: 'show', status: :created, location: @player }
      else
        format.html { render action: 'new' }
        format.json { render json: @player.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /players/1
  # PATCH/PUT /players/1.json
  def update
    respond_to do |format|
      if @player.update(player_params)
        format.html { redirect_to @player, notice: 'Player was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @player.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /players/1
  # DELETE /players/1.json
  def destroy
    @player.destroy
    respond_to do |format|
      format.html { redirect_to players_url }
      format.json { head :no_content }
    end
  end

  def manage_furni
    @player = Player.find(params[:id])
    @furni = Furni.all
  end

  def add_furni
    player = Player.find(params[:id])
    player.furnis << Furni.find(params[:furni])
    redirect_to manage_furni_path(player)
  end

  def remove_furni
    player = Player.find(params[:id])
    item = InventoryItem.find(params[:item])
    player.inventory_items.delete(item)
    redirect_to manage_furni_path(player)
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_player
      @player = Player.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def player_params
      params.require(:player).permit(:name, :room_id, :skin_id, :head_id, :torso_id, :legs_id, :x_position, :y_position, :direction, :action, :gender)
    end
end

更新3:日志

(
    "Processing by PlayersController#create as JSON",
    "Completed 400 Bad Request in 31ms",
    "ActionController::ParameterMissing (param not found: player):",
    "app/controllers/players_controller.rb:103:in `player_params'",
    "app/controllers/players_controller.rb:40:in `create'",
    "Rendered /Users/drewwyatt/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_source.erb (0.5ms)",
    "Rendered /Users/drewwyatt/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_trace.erb (0.9ms)",
    "Rendered /Users/drewwyatt/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (0.8ms)",
    "Rendered /Users/drewwyatt/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (16.3ms)"
){
}

你是否在控制器中编写了一个要求玩家参数的方法?https://github.com/rails/strong_parameters - thank_you
你能否展示一下你整个控制器的代码呢?谢谢。 - thank_you
@jason328 刚刚添加了它。 - drewwyatt
你能否在日志文件中发布POST请求到达服务器的那一行?我只是想确保参数从Postman正确传递。 - Rajesh Kolappakam
@RajeshKolappakam,我在更新3中刚刚添加了它。很抱歉让你等这么久才回复你 - 我今天才看到你的评论。感谢你的帮助! - drewwyatt
显示剩余6条评论
2个回答

70
首先,我认为您的数据格式是正确的,不是问题所在。当我遇到完全相同的问题时,是因为我没有在请求中发送 Content-Type: application/json 头部信息。
在Postman中,您可以选择“原始”数据格式,然后选择“JSON(application/json)”以包含此头部信息。在我的情况下,它看起来像这样:

Screenshot of sending a JSON request to a rails application in Postman

或者,您还可以尝试使用 curlsource):

curl -X POST -H "Content-Type: application/json" -d '{"player": {"name": "test","room_id": 0,"skin_id": 1,"head_id": 2,"torso_id": 3,"legs_id": 4,"x_position": 5,"y_position": 6,"direction": 7,"action": "","gender": "f"}}' localhost:3000/players.json

如果省略-H "Content-Type: application/json",则会收到400响应并显示“未找到参数”错误;如果包含它,则应该可以正常工作。


我在使用 Rails 服务器时遇到了问题。当我通过 Postman 发送 JSON 并设置所有标头时,它可以工作。但是,当我使用我的 iOS 代码发送相同的内容时,它会给我返回 500 错误。我已经困扰了五天了。 - Muhammad Shauket

6

如果您正在尝试以下操作:

通过Postman - 在“form-data”选项卡下,您需要将vars设置为:

player[name]
player[room_id]
.
.

通过jQuery:

$.ajax({ url: 'url', type: 'post', data: { player: { name: 'Test', room_id: '0' } } })

1
谢谢,这对于让PyCurl以Rails兼容的方式发送数据并修复我遇到的408错误非常有用。 - Leo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接