【问题标题】:Spring JSON request body not mapped to Java POJOSpring JSON 请求正文未映射到 Java POJO
【发布时间】:2016-12-21 22:56:45
【问题描述】:

我正在使用 Spring 来实现 RESTful Web 服务。其中一个端点将 JSON 字符串作为请求正文,我希望将其映射到 POJO。但是,现在看来传入的 JSON 字符串不是映射到 POJO 的属性。

这是@RestController 接口

@RequestMapping(value="/send", headers="Accept=application/json", method=RequestMethod.POST)
public void sendEmails(@RequestBody CustomerInfo customerInfo);

数据模型

public class CustomerInfo {
    private String firstname;
    private String lastname; 
    public CustomerInfo() {
        this.firstname = "first";
        this.lastname = "last";
    }

    public CustomerInfo(String firstname, String lastname)
    {
        this.firstname = firstname;
        this.lastname = lastname;
    }

    public String getFirstname(){
        return firstname;
    }

    public void setFirstname(String firstname){
        this.firstname = firstname;
    }

    public String getLastname(){
        return lastname;
    }

    public void getLastname(String lastname){
        this.lastname = lastname;
    }
}

最后是我的 POST 请求:

{"CustomerInfo":{"firstname":"xyz","lastname":"XYZ"}}

Content-Type 指定为 application/json

但是,当我打印出对象值时,会打印出默认值(“first”和“last”),而不是我传入的值(“xyz”和“XYZ”)

有人知道为什么我没有得到预期的结果吗?

修复

原来,请求体的值并没有传入,因为我不仅需要在我的接口中,而且在实际的方法实现中都需要有@RequestBody注解。有了这个,问题就解决了。

【问题讨论】:

  • 如果你把那个 json 扁平化怎么办:{"firstname":"xyz","lastname":"XYZ"}
  • 嗨@mszymborski,我试过了,但也没有用。使用了默认构造函数。
  • 尝试在@RequestMapping 中使用consumes 属性,而不是使用headers
  • 问题出在 Jackson 之外,然后 - 原始 ObjectMapper 在扁平化版本中工作得很好。
  • 嗨@11thdimension,也试过了。没有帮助。

标签: java json spring spring-mvc jackson


【解决方案1】:

这个格式很糟糕,但这应该适用于杰克逊配置。

<!-- Use Jackson for JSON conversion (POJO to JSON outbound). -->
<bean id="jsonMessageConverter"
            class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/> 

<!-- Use JSON conversion for messages -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="messageConverters">
        <list>
            <ref bean="jsonMessageConverter"/>
        </list>
    </property>
</bean>

另外,正如评论中提到的,您的 JSON 对于您的对象是错误的。

{"firstname":"xyz",‌​"lastname":"XYZ"}

对于您的对象来说似乎是正确的 JSON。

【讨论】:

    【解决方案2】:

    你可以通过多种方式做到这一点,这里我将通过以下不同的方式来做到这一点-

    NOTE: 请求数据应该是 {"customerInfo":{"firstname":"xyz","lastname":"XYZ"}}

    1st way我们可以将上面的数据绑定到地图上,如下所示

    @RequestMapping(value = "/send", headers = "Accept=application/json", method = RequestMethod.POST)
    public void sendEmails(@RequestBody HashMap<String, HashMap<String, String>> requestData) {
    
        HashMap<String, String> customerInfo = requestData.get("customerInfo");
        String firstname = customerInfo.get("firstname");
        String lastname = customerInfo.get("lastname");
        //TODO now do whatever you want to do.
    }
    

    2nd way我们可以直接绑定到pojo上

    step 1创建dto类UserInfo.java

    public class UserInfo {
        private CustomerInfo customerInfo1;
    
        public CustomerInfo getCustomerInfo1() {
            return customerInfo1;
        }
    
        public void setCustomerInfo1(CustomerInfo customerInfo1) {
            this.customerInfo1 = customerInfo1;
        }
    }
    

    step 1.创建另一个dto类CustomerInfo.java

    class CustomerInfo {
            private String firstname;
            private String lastname;
    
            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;
            }
        }
    

    step 3绑定请求体数据到pojo

     @RequestMapping(value = "/send", headers = "Accept=application/json", method = RequestMethod.POST)
        public void sendEmails(@RequestBody UserInfo userInfo) {
    
            //TODO now do whatever want to do with dto object
        }
    

    希望对你有所帮助。谢谢

    【讨论】:

    • 非常感谢您提供非常详细的回答。您建议的所有方式都将完成转换技巧。虽然它们不能解决我的问题,但我仍然很高兴学习所有这些。
    • 有没有办法将它简单地绑定到方法参数名称,而不是引入一个新的java类或任意映射到键值对映射?
    【解决方案3】:

    从默认构造函数中删除这两个语句并尝试

    【讨论】:

      【解决方案4】:

      原来,请求体的值并没有传入,因为我不仅需要在我的接口中,而且在实际的方法实现中都需要有@RequestBody注解。有了这个,问题就解决了。

      【讨论】:

        【解决方案5】:

        样本数据:

        [  
        {  
          "targetObj":{  
             "userId":1,
             "userName":"Devendra"
          }
        },
        {  
          "targetObj":{  
             "userId":2,
             "userName":"Ibrahim"
          }
        },
        {  
          "targetObj":{  
             "userId":3,
             "userName":"Suraj"
          }
        }
        ]
        

        对于以上数据,这个pring控制器方法对我有用:

        @RequestMapping(value="/saveWorkflowUser", method = RequestMethod.POST)
        public void saveWorkflowUser (@RequestBody List<HashMap<String ,HashMap<String , 
          String>>> userList )  {
            System.out.println(" in saveWorkflowUser : "+userList);
         //TODO now do whatever you want to do.
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-12-15
          • 2017-01-31
          • 2016-10-20
          • 1970-01-01
          • 2018-11-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多