Trey Parrish
Trey Parrish

Reputation: 5

ajax json Post to Spring mvc Controller "415 Unsupported Media Type"

Hi so I am having problems with getting the JSON from my form to my work with spring mvc. My form is dynamic and the JSON comes back as a list of the criteria that the user filled out on the form. Ideally I would like to be able to get the JSON to come over as a Criterias object which contains a list of Criteria objects. (Like my model classes below) I dont know if this is possible or if there is a different way to go about it but any advice would be much appreciated.

**Currently I am receiving a 415 unsupported Media Type from the ajax post.

CONTROLLER

@RestController   
public class Controller {
@RequestMapping(value-"/test",method=RequestMethod.GET
public ModelAndView getTest(){

ModelAndView model = new ModelAndView("test");

}
@RequestMapping(value-"/query",method=RequestMethod.POST
public ModelAndView submitTest(@RequestBody Criterias criterias){

//do stuff....
ModelAndView model = new ModelAndView("results");

}

MODEL

public class Criterias{
private List<Criteria> criteria = new ArrayList<Criteria>();
getter setter...
}

public class Criteria{
private String field;
private String filter;
private String operator;
private String criteria;


getters setters...
}

TEST.JSP

$(document).ready(function() {
  $("#theButton").click(function() {
    $('#myTable').append("<tr><td><select name = 'operator'><option>AND</option><option>OR</option></select></td><td>Field:<select name='field'><option>a</option><option>b</option> <option>c</option> <option>d</option> </select> </td> <td> <select name='filter'>  <option>Contains</option> <option>Does Not Contain</option> <option>Equals</option> <option>Does Not Equal</option> </select> </td><td>  <input name='criteria' type='text'> </td><td><button type ='button' class ='rm' title = 'Remove Row'/></td></tr>")
  });
  $("#myTable").on('click', '.rm', function() {
    $(this).parent().parent().remove();
  });
});

function post() {

  $.ajax({
    type: "POST",
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    url: "query",
    data: JSON.stringify($('form').serializeArray())

  })

};
<html>

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
</head>

<form>

  <table>
    <tbod>
      <tr>
        <td>Field:
          <select name='field'>
            <option>a</option>
            <option>b</option>
            <option>c</option>
            <option>d</option>
          </select>
        </td>
        <td>
          <select name='filter'>
            <option>Contains</option>
            <option>Does Not Contain</option>
            <option>Equals</option>
            <option>Does Not Equal</option>
          </select>
        </td>
        <td>
          <input name='criteria' type='text'>
        </td>
      </tr>
    </tbod>
  </table>
  <table id='myTable'>
    <tbody>
    </tbody>
  </table>

  <input type="button" value="search" onclick="return post();">
  <input type="button" id="theButton" value="Add Criteria">

</form>

UPDATE

I attempted to do something a little simpler to narrow down the issue and from what I have looked up it seems to be a problem with the jackson mapping. The following code produces 415 error as well.

Controller

@RestController
public class Rest{
@RequestMapping(value="/testModel",method=RequestMethod.GET)
public ModelAndView getTestModel(){
   return new ModelAndView("testModel");
}

 @RequestMapping(value="/sendTestModel",method=RequestMethod.POST)
 public String submiteTestModel(@RequestBody TestModel test){
   return test.getName();
 }
 }

MODEL

public class TestModel{

private String id;
private String name;

//getters setters....
}

testModel.jsp

function post() {

    $.ajax({
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
          },
          type: "POST",
          contentType: 'application/json;,
    dataType: '
          json ',
    url: "sendTestModel",
    data: JSON.stringify({id:"1",name:"Bob"})

  })

};
<Html>
<input type="button" value="search" onclick="return post();"/>
</Html>

Upvotes: 0

Views: 7231

Answers (2)

Bnrdo
Bnrdo

Reputation: 5474

Calling JSON.stringify($('form').serializeArray()) will give you the following String

[{"name":"field","value":"a"},{"name":"filter","value":"Contains"},{"name":"criteria","value":""}]

Here is the documentation for serializeArray()

Clearly, this is not acceptable for a @RestController that expects JSON representation of Criterias object. Your JSON string should look like

{"criteria":[{"field":"a","filter":"Contains"},{"field":"Some other field value","filter":"Some other filter value"}]}

I have made a simple function to do it for you :

function convertCriterias(json){
    var o = new Object();
    var criterias = [];
    var c = new Object();

    for(var i = 0; i < json.length; i++){
        c[json[i].name] = json[i].value;
    }

    criterias[0] = c;

    o.criteria = criterias;

    return JSON.stringify(o);
}

Just replace JSON.stringify($('form').serializeArray()) with convertCriterias($('form').serializeArray())

EDIT

I believe you meant to use input type="button" instead of input type="submit" for doing an AJAX post to your @RestController. And you meant to call return work() and not return post in the onclick event of the button.

Upvotes: 2

dimitrisli
dimitrisli

Reputation: 21411

Try the following options:

  • Add in your controller's RequestMapping the content-type you want to get produced. Take a look at the Producible Media Types documentation for more information.

    @ResponseBody @RequestMapping(value="/query", method=RequestMethod.POST, produces="application/json")

  • Explicitly specify the Accept request header not just the Content-Type header in your jQuery Ajax call:

    $.ajax({
    headers: {
    Accept : "application/json; charset=utf-8",
    "Content-Type": "application/json; charset=utf-8"
    },.. })

Upvotes: 0

Related Questions