我们是否必须 post json 对象具有与控制器中的 pojo 对象完全相同的字段?

Do we have to have to post json object with exactly same fields as in pojo object in controller?

我是 spring 休息的新手,在将 JSON 对象从 jquery 映射到控制器时遇到问题。我的 jquery JSON 对象缺少某些字段,但存在于控制器上的 java 对象中。我是否必须创建新的 class 来映射此类对象,或者是否有任何方法可以在不创建新的 class 的情况下映射这些对象?

这是代码

控制器:

@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

测试集:

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;

主要问题:

public class MainQuestion implements Serializable {

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

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

和我的jquerypost方法

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()
    })

}

JSON.stringify 中,我不会发送 TestJsonDto 中的所有字段。我该如何映射?

您应该这样配置 Spring:

@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;
    }
}

此处 Spring 配置了一个 ObjectMapper,它不会序列化值为 null 的属性,并且如果某些 属性 是,则反序列化不会失败失踪。

编辑:(添加了一些背景和解释)

Spring 将 HTTP 请求正文中的内容转换为 POJO(这就是 @RequestBody 实际上告诉 Spring 要做的事情)。这种转换是由一个抽象的 HttpMessageConverter 执行的。 Spring 为常用媒体类型提供默认的特定消息转换器,例如 Strings、JSON、表单字段等

在您的情况下,您需要告诉 Spring 如何反序列化传入的 JSON,即如何读取您从 jQuery 发送的 JSON以及如何将此 JSON 转换为您希望在 @Controller 中收到的 POJO(在您的问题中为 TestJsonDTO)。

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,它可以接收 Jackson 的 ObjectMapper 实例,如果您想覆盖默认行为,您可以配置该实例。

ObjectMapper 配置为不序列化 POJO 中 null 的属性(即,您的 JSON 不会将这些属性作为字段包含),更重要的是,当反序列化,它被配置为如果在您的 JSON 或您的 POJO 中缺少 属性 则不会失败并出现异常。这就是 objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); 实际所做的。