【问题标题】:Convert a object into JSON in REST service by Spring MVC通过 Spring MVC 将对象转换为 REST 服务中的 JSON
【发布时间】:2015-05-18 12:44:39
【问题描述】:

我正在尝试使用 Spring MVC 创建一个 REST 服务,如果我返回一个纯字符串,它就可以工作。我的要求是返回 Java 对象的 JSON 字符串。不知道如何通过隐式转换来实现。

这是我的代码:

StudentService.java

package com.spring.schoolmanagement.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.spring.schoolmanagement.dao.CourseDAOImpl;
import com.spring.schoolmanagement.dao.StateDAOImpl;
import com.spring.schoolmanagement.dao.StudentDAOImpl;
import com.spring.schoolmanagement.model.Student;

@Controller
@RequestMapping("/rest/student")
public class StudentService {

    @Autowired
    private CourseDAOImpl courseService;
    @Autowired
    private StudentDAOImpl studentService;
    @Autowired
    private StateDAOImpl stateService;


    @RequestMapping(value = "/{id}", method = RequestMethod.GET, headers = "Accept=*/*")
    @ResponseBody
    public Student home(@PathVariable int id) {
        return this.studentService.getById(id);
    }

    @RequestMapping(method = RequestMethod.GET, headers = "Accept=*/*")
    @ResponseBody
    public List<Student> getAll() throws Exception {
        return this.studentService.getAll();
    }

    @RequestMapping(value = "/test", method = RequestMethod.GET, headers = "Accept=*/*")
    @ResponseBody
    public String test() {
        return "Test REST Service!!!";
    }
}

Student.java

package com.spring.schoolmanagement.model;

import java.util.Date;

import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;

public class Student extends Contact{
    private int id;

    @NotEmpty
    @Size(max = 30)
    private String firstName, lastName;
    //private String lastName;

    @DateTimeFormat(pattern="MM/dd/yyyy")
    private Date DOB, DOA;
    //private Date DOA;

    @NotEmpty
    @Email
    private String email;
    private String password;
    private int courseID;
    private String courseName;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public Date getDOB() {
        return DOB;
    }
    public void setDOB(Date dOB) {
        DOB = dOB;
    }
    public Date getDOA() {
        return DOA;
    }
    public void setDOA(Date dOA) {
        DOA = dOA;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public int getCourseID() {
        return courseID;
    }
    public void setCourseID(int courseID) {
        this.courseID = courseID;
    }
    public String getCourseName() {
        return courseName;
    }
    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }
}

这里 http://localhost:8080/schoolmangement/rest/student/test URL 正在返回“测试 REST 服务!!!”

但是,http://localhost:8080/schoolmangement/rest/student/1 URL 抛出 HTTP 状态代码 406 并显示错误消息:

此请求标识的资源只能生成具有根据请求“接受”标头不可接受的特征的响应。

【问题讨论】:

  • 我不知道你为什么指定headers = "Accept=*/*",但是你应该指定produces = "application/json"
  • 您的 Spring 配置可能不包括 Jackson 映射器。使用 Spring Boot 进行配置,它会自动配置一个,如果您没有使用解耦 DTO 来表示外部 API,请考虑使用 Spring Data REST。
  • @chrylis,是的,你是对的。最后我得到了解决方案。

标签: java json spring rest spring-mvc


【解决方案1】:

最后我得到了使用 Jackson 库和 Spring MVC 的解决方案。我从 Journal Dev 的示例中得到了这个解决方案(http://www.journaldev.com/2552/spring-restful-web-service-example-with-json-jackson-and-client-program

所以,我所做的代码更改是:

  • 在 Maven 中包含该库。
  • 将 JSON 转换 Servlet 添加到 servlet-context.xml 中。
  • 将模型更改为可序列化。

我没有对我的 REST 服务控制器进行任何更改。默认情况下,它会转换为 JSON。

【讨论】:

  • 有同样的问题,并按照完全相同的步骤来解决它。发送。
【解决方案2】:

您始终可以在 Web 方法上方添加 @Produces("application/json") 或指定 produces="application/json" 以返回 json。然后在Student 类的顶部,您可以从javax.xml.bind.annotation 包中添加@XmlRootElement

请注意,直接返回模型类可能不是一个好主意。只是一个建议。

HTH。

【讨论】:

  • 我尝试使用 xml 绑定,但我做不到。从这篇文章(journaldev.com/2552/…)我做到了。
  • 现在 - 我们甚至不需要注释类。只需在类路径上添加 jackson 并返回 POJO、该 POJO 的列表、包含 pojo 作为值的 Map,它仍然可以工作。
【解决方案3】:

当控制器被正确注释时,Spring 框架本身会处理 json 转换。

例如:

   @PutMapping(produces = {"application/json"})
        @ResponseBody
        public UpdateResponse someMethod(){ //do something
return UpdateResponseInstance;
}

这里spring内部将UpdateResponse对象转换为对应的json字符串并返回。为了做到这一点,spring在内部使用Jackson library.

如果您需要除控制器之外的任何地方的模型对象的 json 表示,那么您可以使用 jackson 提供的 objectMapper。应正确注释模型以使其正常工作。

例如:

ObjectMapper mapper = new ObjectMapper();
SomeModelClass someModelObject = someModelRepository.findById(idValue).get();
mapper.writeValueAsString(someModelObject);

【讨论】:

    【解决方案4】:


    Json 转换应该是开箱即用的。为此,您需要添加一些简单的配置:
    首先将 contentNegotiationManager 添加到您的 spring 配置文件中。它负责协商响应类型:

    <bean id="contentNegotiationManager"
          class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
        <property name="favorPathExtension" value="false" />
        <property name="favorParameter" value="true" />
        <property name="ignoreAcceptHeader" value="true" />
        <property name="useJaf" value="false" />
         <property name="defaultContentType" value="application/json" />
    
          <property name="mediaTypes">
             <map>
                <entry key="json" value="application/json" />
                <entry key="xml" value="application/xml" />
             </map>
          </property>
       </bean>
    
       <mvc:annotation-driven
          content-negotiation-manager="contentNegotiationManager" />
    
       <context:annotation-config />
    

    然后在服务的类路径中添加 Jackson2 jar(jackson-databind 和 jackson-core)。 Jackson 负责将数据序列化为 JSON。 Spring 将检测到这些并自动为您初始化 MappingJackson2HttpMessageConverter。 只配置了这个,我就可以自动转换为 JSON。如果您设置 accept:application/xml 标头,所描述的配置还有一个额外的好处,即让您可以序列化为 XML。

    【讨论】:

      【解决方案5】:

      另一个简单的解决方案是在 POM 中添加 jackson-databind 依赖。

          <dependency>
              <groupId>com.fasterxml.jackson.core</groupId>
              <artifactId>jackson-databind</artifactId>
              <version>2.8.1</version>
          </dependency>
      

      保持其余代码不变。

      【讨论】:

        猜你喜欢
        • 2021-05-17
        • 2015-06-11
        • 2014-12-31
        • 1970-01-01
        • 2016-01-30
        • 2021-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多