2016-04-03 79 views
1

我正在Java Spring中编写Web应用程序。我有下面显示的这个MyUser类和一个其他的API。将JSON对象发送给Rest服务时出现“Bad Request”请求

public class MyUsers { 
    String username; 
    String password; 
    boolean enabled; 
    Collection<GrantedAuthority> roles; 

    //getters, setters 
} 

在UserController的一些方法:

@RequestMapping(value="/users", method = RequestMethod.POST) 
@ResponseStatus(HttpStatus.CREATED) 
ResponseEntity createUser(Principal principal, @RequestBody @Valid MyUser user) { 
    ... 
} 


@RequestMapping(value = "https://stackoverflow.com/users/{username}", method = RequestMethod.GET) 
public @ResponseBody MyUser getUser(HttpServletResponse response, Principal principal, @PathVariable("username") String username) { 

    ... 
} 

从GET方法我收到此JSON:

{ 
    "password":"5345345345", 
    "enabled":true, 
    "roles":[{"authority":"ROLE_ADMIN"}], 
    "username":"admin" 
} 

然而,当我使用POST方法,我不能指定角色,我只能发送一个下面的对象,否则我会收到“错误的请求”错误。

{ 
    "password":"5345345345", 
    "enabled":true, 
    "roles":[], 
    "username":"admin" 
} 

我希望能够指定角色。 任何想法如何解决这个问题将不胜感激。

编辑:

我试过这个,但它没有帮助。有错误吗?

public class UserDeserializer extends JsonDeserializer<MyUser> { 

    @Override 
    public MyUser deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) 
      throws IOException { 

     MyUser MyUser = new MyUser(); 

     ObjectCodec oc = jsonParser.getCodec(); 
     JsonNode node = oc.readTree(jsonParser); 

     Iterator<JsonNode> elements = node.get("roles").getElements(); 
     while (elements.hasNext()) { 
      JsonNode next = elements.next(); 
      JsonNode authority = next.get("authority"); 
      MyUser.getRoles().add(new SimpleGrantedAuthority(authority.asText())); 
     } 
     //System.out.println(MyUser.toString()); 
     return MyUser; 
    } 
} 

@JsonDeserialize(using = UserDeserializer.class) 
public class MyUser{ 
    String username; 
    String password; 
    boolean enabled; 
    List<GrantedAuthority> roles; 

    //getters, setters 
} 
+1

看起来Jackson在反序列化Spring安全'GrantedAuthority'对象方面存在困难。您可以尝试使用Jackson自定义解串器来实现此目的。 – Bunti

+1

当然[这](http://stackoverflow.com/questions/35724693/jackson-deserialize-object-with-list-of-springs-interface)发布可能会对你有所帮助, – Bunti

+0

嗯,我试过,但有一些问题,我应该在MyUser类中添加@JsonDeserialize注释吗? – Someone

回答

1

提到基于更新后的代码的方式之一,告知杰克逊图书馆有关具体的类,你用过@JsonDeserializeMyUser类,这是我认为没有必要,因为杰克逊已经知道如何反序列化MyUser类除roles字段以外的所有字段。我建议在roles字段级别使用@JsonDeserialize,这样您就不必反序列化整个MyUser类,只需要杰克逊无法反序列化的字段。

作为一个优势,如果您希望添加新的字段,您不需要修改您的自定义解串器,不改变API并不是一件好事。

这样的事情就足够了。

public class GrantedAuthorityDeserializer extends JsonDeserializer<Collection<GrantedAuthority>> { 

@Override 
public Collection<GrantedAuthority> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) 
     throws IOException, JsonProcessingException { 

    JsonNode jsonNode = jsonParser.getCodec().readTree(jsonParser); 
    Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); 
    if (jsonNode.isArray()) { 
     // you may have different serialization logic if you want 
     for (JsonNode node : jsonNode) { 
      authorities.add(new SimpleGrantedAuthority(node.get("authority").asText())); 
     } 
    } 

    return authorities; 
    } 
} 

,并在roles场使用@JsonDeserialize

@JsonDeserialize(using = GrantedAuthorityDeserializer.class) 
Collection<GrantedAuthority> roles; 

我假设你有杰克逊2 classpath中。