How should I format a JSON POST request to my rails app?

57,652

Solution 1

First of all, I think your data format is ok and is not the problem here. When I ran exactly into the same problem it was because I did not send the Content-Type: application/json header along with my request.

In Postman, you can select the 'raw' data format and then 'JSON (application/json)' to include this header. In my case it looks like this:

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

Alternatively, you can also try it with curl (source):

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

If you omit the -H "Content-Type: application/json", then you will receive a 400 response with the "param not found" error, if you include it it should work.

Solution 2

If you are trying this:

via Postman - Under form-data tab, you need to have the vars as :

player[name]
player[room_id]
.
.

via jQuery:

$.ajax({ url: 'url', type: 'post', data: { player: { name: 'Test', room_id: '0' } } })
Share:
57,652
drewwyatt
Author by

drewwyatt

Typed language enthusiast, Texas native, and obsessive automator.

Updated on November 02, 2020

Comments

  • drewwyatt
    drewwyatt over 3 years

    My Rails app has a player class that works perfectly. Players can be created, deleted, and updated from my rails control panel without any issues.

    I would like a remote counterpart to be able to join in the fun by creating players using a JSON request. Following the advice of the auto generated Rails comments above my create method : # POST /players.json I have started sending requests to localhost:3000/players.json

    The 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"
        }
    }
    

    However, I am running into this error message:

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

    So I guess my question is: How should I structure the JSON I am sending?

    Additional info:

    • Ruby Version: 2.0
    • Rails Version: 4.0
    • I have tried sending my requests using Postman

    Update - Player Params

    Here is the player params method from my controller (as requested):

    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
    

    Update 2 - Player controller

    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
    

    Update 3: logs

    (
        "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)"
    ){
    }
    
  • Muhammad Shauket
    Muhammad Shauket over 8 years
    i am facing issue with rail serever when i send json via post man and all header set it works on postman but when same thing i send using my ios code it give me error 500 i am messed up from 5 days on this issue
  • Leo
    Leo over 5 years
    Thanks, this was useful for getting PyCurl to send data in a Rails-compatible way and fix the 408 errors I was getting.