'How do you send JSON data in a rails-ujs Rails.ajax POST call (not using jQuery)?

I have a React client app that needs to talk to a Rails API. I want to use the rails-ujs method Rails.ajax. For example:

Rails.ajax({
  type: "POST", 
  url: "/things",
  data: mydata,
  success: function(response) {...},
  error: function(response) {...}
})

It looks like I can't set data to a JSON object like this:

mydata = {
 thing: {
  field1: value1,
  field2: value2,
}}

I need to convert it to a application/x-www-form-urlencoded content type manually like this:

mydata = 'thing[field1]=value1&thing[field2]=value2'

This is ok for flat data but gets complicated quickly for nested data.

jQuery does the conversion automatically before making a request.

So I'm wondering if Rails UJS has some automatic way of doing it, but I couldn't find anything in the docs or code.



Solution 1:[1]

When using Rails UJS, data must be formatted as string form parameters. Unfortunately, it's not possible to provide JSON, at least not currently with Rails 6.0.2 (not ideal).

Solution

Use URLSearchParams to convert JSON to URL paramaters:

myData = {
 thing: {
  field1: value1,
  field2: value2,
}}

Rails.ajax({
  type: "POST",
  url: "/things",
  data: new URLSearchParams(myData).toString()
})

Solution 2:[2]

Here is my workaround to put/post with Content-Type: application/json.

It works by setting options.data in the beforeSend callback. This way the internal Rails.ajax.createXHR method does not set the Content-Type header first. https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts/rails-ujs/utils/ajax.coffee#L53

    Rails.ajax({
      url: 'http://some-url.com',
      type: 'put',
      beforeSend(xhr, options) {
        xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8')
        // Workaround: add options.data late to avoid Content-Type header to already being set in stone
        // https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts/rails-ujs/utils/ajax.coffee#L53
        options.data = JSON.stringify(data)
        return true
      },
    });

Solution 3:[3]

I used ajax call several times and I used to send json data like this.

var fd = new FormData();
fd.append("jsondata", JSON.stringify(mydata));

$.ajax({
  url: ...
  type :"post",
  data: fd
  success:function(){
  }
})

Parsing Json data in ruby controller is easy. you can just use JSON.parse(params["jsondata"])
Hope this works for your case.

Solution 4:[4]

I reviewed the library code and It doesn't support that because in order to send an object you have to stringify the object, and after doing that I discovered that the library checks if the data is the type of string It changes the content type of the request to application/x-www-form-urlencoded . This link shows that condition in the library. And for that, your option to overcome this issue is to write a method that transforms the object to input form way or use JQuery Ajax or another library.

Solution 5:[5]

Not sure if I'm misunderstanding the issue, but can't you just convert your object using JSON.stringify?

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

Certainly I can see in the rails-ujs module it's using JSON.parse to parse the Json response

Solution 6:[6]

I noticed no actual solution for the stated problem, just workarounds.

Here is a link to a gist (JS class) that will handle the required serialization:

https://gist.github.com/dansimpson/231546

Solution 7:[7]

you can set the content type in your ajax call and sending the data in json format

var data={
      user:{
        first_name: firstname,
        last_name: lastname,
        username: username
      }}

send the ajax call by placing content type as json in http header request

$.ajax({
   type: "POST",
   url: "http://someurl/post",
   data:data,
   contentType: "application/json",
   success: function(data) {
       -------
  }
});?

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jeremy Lynch
Solution 2 Freddy
Solution 3 artgb
Solution 4 Ahmed Magdy
Solution 5 DJ Forth
Solution 6 Vlad
Solution 7 Geetha Tulasi Balam