4

I am new to spring rest and am having problem to map JSON object from jquery to controller. My jquery JSON object have some field absent which are present in java object on controller. Do I have to create new class to map such object or is there any way to map these objects without creating new class?

Here are the code

Controller:

@RequestMapping(value = "/createTest", method = RequestMethod.POST,consumes="application/json")
    @ResponseBody
    public String createTest(@RequestBody TestJsonDTO testJson)
            throws JsonProcessingException, IOException {
//....

TestJsonDTO:

 public class TestJsonDTO {

 private TestSet testSet;

 private List<MainQuestion> questionsInTest;

 //gettters and setters

TestSet:

public class TestSet implements Serializable {

public TestSet() {
}

@Id
@GeneratedValue
private int id;
private String name;
private int fullmark;
private int passmark;
String duration;
Date createDate = new Date();
Date testDate;
boolean isNegativeMarking;
boolean negativeMarkingValue;

MainQuestion:

public class MainQuestion implements Serializable {

private static final long serialVersionUID = 1L;
public MainQuestion() {

}
@Id
@GeneratedValue
private int id;
private String name;

and my jquery post method

function createTest() {
    $.ajax({
        type : 'POST',
        url : "http://localhost:8085/annotationBased/admin/createTest",
        dataType : "json",
        contentType : "application/json",
        data : testToJSON(),
        success : function() {
            alert("success")
        },
        error : function(msg) {
            alert("error while saving test");
        }
    });

}

function testToJSON() {
    listOfQuestionForTest = questionToAdd;//array of ids of questions
    return JSON.stringify({
        "testSet.name" : $('#testname').val(),
        "testSet.fullmark" : parseInt($('#fullmark').val()),
        "testSet.passmark" : parseInt($('#passmark').val()),
        "questionsInTest" : listOfQuestionForTest
    // "testDate":$('#testDate').value()
    })

}

In JSON.stringify I am not sending all the fields in TestJsonDto. How can I map this?

Meno Hochschild
  • 42,708
  • 7
  • 104
  • 126
CodeBlooded
  • 185
  • 5
  • 16
  • This might help you : http://stackoverflow.com/questions/5908466/jquery-spring-mvc-requestbody-and-json-making-it-work-together – Runcorn Jan 28 '15 at 18:35
  • Thank u @Meno but this doesn't solve my problem as i just want to send only few fields of TestSet and MainQuestion to Controller through TestJsonDto. My question is do i have to create a new class to do this? – CodeBlooded Jan 28 '15 at 18:49

1 Answers1

2

You should configure Spring this way:

@Configuration
public class ServiceContext
    extends WebMvcConfigurationSupport {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter converter = this.getMappingJackson2HttpMessageConverter();
        converters.add(converter);
    }

    @Bean
    public MappingJackson2HttpMessageConverter getMappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = this.getObjectMapper();
        mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
        return mappingJackson2HttpMessageConverter;
    }

    @Bean
    public ObjectMapper getObjectMapper() {
        JsonFactory jsonFactory = new JsonFactory();
        ObjectMapper objectMapper = new ObjectMapper(jsonFactory);
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); // this is what you need
        objectMapper.setSerializationInclusion(Include.NON_NULL); // this is to not serialize unset properties
        return objectMapper;
    }
}

Here Spring is configured with an ObjectMapper that doesn't serialize properties whose value is null and that doesn't fail on deserialization if some property is missing.

EDIT: (Added some background and explanations)

Spring converts what comes in HTTP request's body into a POJO (that's what @RequestBody actually tells Spring to do). This conversion is performed by a HttpMessageConverter, which is an abstraction. Spring provides default specific message converters for common media types, such as Strings, JSON, form fields, etc.

In your case, you need to tell Spring how to deserialize the incoming JSON, i.e. how to read the JSON that you're sending from jQuery and how to convert this JSON into the POJO you're expecting to receive in your @Controller (TestJsonDTO in your question).

Jackson 2 is a JSON serialization/deserialization library that is widely used. It's most important class is ObjectMapper, which is used to perform the actual serialization and deserialization. Spring has a specific HttpMessageConverter that uses Jackson in order to serialize and deserialize JSON. This is MappingJackson2HttpMessageConverter, which can receive a Jackson's ObjectMapper instance that you can configure if you want to override default behavior.

This ObjectMapper is configured to not serialize properties that are null in your POJO (i.e. your JSON won't contain these properties as fields), and more important, when deserializing, it is configured to not fail with an exception if there is a missing property in either your JSON or your POJO. This is what objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); actually does.

fps
  • 33,623
  • 8
  • 55
  • 110
  • thank you Magnamg this worked for me perfectly. But plzz can u elaborate your ans , Thank u – CodeBlooded Jan 28 '15 at 19:42
  • magnamag ,sorry for bothering again , but I have a problrm again The Post is ok, but i'm getting 415 error.Yes I have seen other related post but non of them solved my problem. – CodeBlooded Feb 02 '15 at 04:23
  • @SumitShrestha 415 means unsupported media type. It means the server is responding with a `Content-Type` header in the response different than the one you're sending in the request's `Accept` header. Both `Accept` and `Content-Type` headers in the request, as well as `Content-Type` header in the response, should be `application/json`. Sometimes a charset is added to the `Content-Type` header, i.e. `application/json; charset=utf8`. Maybe you're receiving 415 because request's `Accept` header is just `application/json`, while response's `Content-Type` header also includes the charset. – fps Feb 02 '15 at 04:36
  • @SumitShrestha And yes, you should have posted another question ;) – fps Feb 02 '15 at 04:37
  • here is the link for question http://stackoverflow.com/questions/28271304/415-error-while-ajax-post-in-spring-rest> please it will be great if you add code too in your answer. thank u in advance – CodeBlooded Feb 02 '15 at 04:52