如何将包含子类的Java集合发送到spring控制器

时间:2016-04-12 19:02:40

标签: spring spring-mvc collections

我试图将集合发送到我的spring MVC控制器:

@RequestMapping("/postUsers.do")
public @ResponseBody ResponseDTO postUsers(@ModelAttribute("mapperList") MapperList mapperList) {
    //prints {"users":null}
    System.out.println(new ObjectMapper().writeValueAsString(mapperList));
    return new ResponseDTO();
}

这是发布我的用户的代码:

  public ResponseDTO postUsers(ArrayList<User> users) {
            ResponseDTO serverResponse = null;
            URL url = new URL(urlString);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            connection.setRequestMethod("POST");
            // prints {"users":[{"property1":"x","property1":y}]}
            System.out.println(objectMapper.writeValueAsString(new MapperList(users)));
            objectMapper.writeValue(connection.getOutputStream(), objectMapper.writeValueAsString(new MapperList(users)));
            //blabla ...
    }

这是包含我的列表的对象:

public class MapperList implements Serializable {

    private static final long serialVersionUID = 8561295813487706798L;

    private ArrayList<User> users;

    public MapperList() {}

    public MapperList(ArrayList<User> users) {
        this.setUsers(users);
    }

    public ArrayList<User> getUsers() {
        return users;
    }

    public void setUsers(ArrayList<User> users) {
        this.users = users;
    }
}

这是要发布的用户类型:

public abstract class User implements Serializable {

    private static final long serialVersionUID = -1811485256250922102L;

    private String property1;

    private String property2;

    public User() {}

    public User(String prop1, String prop2) {
        // set properties
    }

// getters and setters

}

问题是,当我输出用户数组的值之后将其发布到控制器时,我得到了以下json值:

{"users":[{"property1":"x","property1":y}]}

但是在控制器中,当我打印从请求正文中得到的内容时,我只得到:

{"users":null}

我还尝试使用注释@RequestBody而不是@ModelAttribute(&#34; mapperList&#34;)并显示JSONException:
* JSONObject文本必须以&#39; {&#39;在1 [字符2行1] \ r \ n * 我的用户数组列表只包含一个应该显示的用户。我不明白为什么这不起作用...... 谢谢你的帮助!

4 个答案:

答案 0 :(得分:0)

在服务器端保留@RequestBody注释:

public @ResponseBody ResponseDTO postUsers(@RequestBody MapperList mapperList)
...

但是这一行导致了问题:

objectMapper.writeValue(
    connection.getOutputStream(),
    objectMapper.writeValueAsString(new MapperList(users))
);

首先,它将对象转换为JSON,然后再次使用objectMapper将字符串JSON编码为输出流。请尝试以下方法:

connection.getOutputStream().write(
    objectMapper.writeValueAsString(new MapperList(users))
        .getBytes("UTF-8")
);

或直接输出到流:

objectMapper.writeValue(
    connection.getOutputStream(),
    new MapperList(users))
);

答案 1 :(得分:0)

您可以将MapperList类定义定义为public class MapperList extends ArrayList<User>{ ..},您不需要像MapperList类中的私有ArrayList用户那样定义任何实例变量。使用@Requestbody注释。您将能够使用MapperList作为ArrayList

答案 2 :(得分:0)

尝试使用:

public class MapperList{
   private List<User> users;

   //setter and getter
   //toString

}

public class User{
    private String property1;
    private String property2;
    //getter + setter
}

JSON:

{"users":[{"property1":"x", "property2":"y"}]}

在控制器中使用@RequestBody。在这种情况下,Jackson会将你的json映射到用户的ArrayList。

@ResponseStatus(HttpStatus.OK)
@RequestMapping("/postUsers.do")
public @ResponseBody ResponseDTO postUsers(@RequestBody MapperList users) {
    System.out.println(users);
    return null;
}

在这种情况下无需获取objectMapper。不要忘记将请求标头中的内容类型设置为application / json。它需要Spring来处理@RequestBody处理。

如果不工作,请尝试更改MapperList:

List<User> users = new ArrayList<User>();

答案 3 :(得分:0)

Zbynek给了我部分答案。确实

objectMapper.writeValue(
    connection.getOutputStream(),
    objectMapper.writeValueAsString(new MapperList(users))
); 

在我的案例中没有正常工作

但是,我的User类是一个抽象类,有许多类型的User作为子类。所以@RequestBody注释无法在Json中指定对象类型的情况下工作。 我在User类上使用了以下注释来使其工作:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
                      @JsonSubTypes.Type(value = SubClassA.class, name = "a"),
                      @JsonSubTypes.Type(value = SubClassB.class, name = "b")
              })

非常感谢您的所有答案。