Deserialization errors in Jackson with duplicated objects with different elements

Viewed 26

I'm trying to understand better some deserialization errors I'm seeing in Jackson in a legacy application being converted to a React front-end with Spring back-end.

I see the error when multiple objects of the same class are referenced in the JSON but they have different elements due to fields being ignored with @JsonIgnoreProperties to eliminate infinite recursion. The Spring application will send JSON to the front-end application from the database. We may manipulate a few fields but keep the same basic structure and when we post it back, it says it can't deserialize it. Here's a simplified example.

File named Child.java

public class Child implements java.io.Serializable {
    private String name;

    @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    private Parent parent;

    public Child() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Parent getParent() {
        return parent;
    }

    public void setParent(Parent parent) {
        this.parent = parent;
    }
}

File name Parent.java

public class Parent implements java.io.Serializable {
    private String name;

    @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
    @JsonIgnoreProperties("parent")
    private Set<Child> children = new HashSet<Child>(0);

    public Parent() {
    }

    public String getName() {
       return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Child> getChildren() {
        return children;
    }

    public void setChildren(Set<Child> children) {
        this.children = children;
    }
}

Controller (normally we would be saving to database here)

@ResponseBody
@RequestMapping(value = "/returnParent", method = RequestMethod.POST)
public ResponseEntity<Parent> returnParent(@RequestBody Child child) throws Exception {
    return new ResponseEntity<Parent>(child.getParent(), HttpStatus.OK);
}

JSON posted

{
    "name":"child1",
    "parent":{
        "name":"parent1",
        "children":[
            {
                "name":"child1"
            },
            {
                "name":"child2"
            }
        ]
    }
}

Error:

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: No _valueDeserializer assigned; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: No _valueDeserializer assigned\n at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 7, column: 24] (through reference chain: ...Child["parent"]->...Parent["children"]->java.util.HashSet[0]->...Child["name\

I know that if I add this

@JsonIgnoreProperties(value={"children"}, allowGetters=true)
private Parent parent;

to Child that it will suppress the error and ignore child.parent.children but what if we need to be able post back these nested structures? This feels like a bug that it can't read the same JSON it created.

0 Answers
Related