Jazzepi
Jazzepi

Reputation: 5480

The request sent by the client was syntactically incorrect - Complicated type in JSON POST body

Using Spring 4 and Jackson 2.x

I'm posting the following JSON to the following controller method. When I post it with the grantedAuthorities filled out with one entry, then I get a 400 The request sent by the client was syntactically incorrect. response.

headers:273 - >> POST /rest/users HTTP/1.1
headers:276 - >> Accept: */*
headers:276 - >> Content-Length: 103
headers:276 - >> Content-Type: application/json; charset=ISO-8859-1
headers:276 - >> Host: localhost:8090
headers:276 - >> Connection: Keep-Alive
headers:276 - >> User-Agent: Apache-HttpClient/4.2.6 (java 1.5)
headers:276 - >> Accept-Encoding: gzip,deflate
wire:77 - >> "{"password":"Password","id":0,"username":"Amy","grantedAuthorities":[{"role":"RANDOM_FAKE_AUTHORITY"}]}"

If I put this in the body, with no granted authorities in the List of granted authorities, it works fine.

{"password":"Password","id":0,"username":"Mike","grantedAuthorities":[]}

I have Jackson 2.0 on my classpath, so I assume that's what it's using to map these Json bodies to objects. I'm just not sure why jackson is choking on the granted authorities, or refusing to process them. Any help would be much appreciated.

Controller
    @RequestMapping(method = RequestMethod.POST)
    @ResponseBody
    public ResponseWithView<User> createUser(@RequestBody User user) {
        return new ResponseWithView<>(userService.save(user), Views.Public.class);
    }

User class that the JSON should be mapping to.
    @Entity
    @Data
    @Accessors(chain=true)
    @EqualsAndHashCode(of = {"username"})
    public class User implements Motherly {
        @Id
        @GeneratedValue
        @JsonView(Views.Public.class)
        private int id;
        @Column(unique = true)
        @JsonView(Views.Public.class)
        private String username;
        private String password;
        @JsonView(Views.Admin.class)
        @ElementCollection(fetch = FetchType.EAGER)
        private List<GrantedAuthority> grantedAuthorities;

GrantedAuthority is an interface from Spring.

public interface GrantedAuthority extends Serializable {
    String getAuthority();
}

In my code I always use the implementation SimpleGrantedAuthority

public final class SimpleGrantedAuthority implements GrantedAuthority {

    private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;

    private final String role;

    public SimpleGrantedAuthority(String role) {
        Assert.hasText(role, "A granted authority textual representation is required");
        this.role = role;
    }

    public String getAuthority() {
        return role;
    }

    public boolean equals(Object obj) {
        if (this == obj) {


   return true;
        }

        if (obj instanceof SimpleGrantedAuthority) {
            return role.equals(((SimpleGrantedAuthority) obj).role);
        }

        return false;
    }

    public int hashCode() {
        return this.role.hashCode();
    }

    public String toString() {
        return this.role;
    }
}

Upvotes: 0

Views: 870

Answers (1)

Nick
Nick

Reputation: 930

Discussion in comments/chat found that problem was Jackson didn't like the missing empty constructor which doesn't exist since you specified one

// add this constructor
public SimpleGrantedAuthority() { 
}

public SimpleGrantedAuthority(String role) {
  Assert.hasText(role, "A granted authority textual representation is required");
  this.role = role;
}

Upvotes: 2

Related Questions