spring-projects / spring-projects/spring-data-rest

Unwrapping of null value objects [DATAREST-1175]

Open
#1,541 0 comments 0 reactions 1 assignee View on GitHub

@odrotbohm is already working on this.

Since Dec 31, 2020.

in: repository type: enhancement
Dominant language
Java
Stars
958
Forks
568
PR merge metrics
No merged PRs in 30d

Description

Patrik Mihalcin opened DATAREST-1175 and commented

Hi..
Let's say I have value object:

@Data
public class Description {
    @Column(name = "DESCRIPTION")
    private final String description;
}

and entity:

@Entity
public class Product extends AbstractEntity<Long> {

    @JsonUnwrapped
    private final Description description; 

    public Product (Description description) {
        this.description = description;
    }

    protected Specification() {
        this.description = new Description(null);
    }
}

and custom Description serializer:

static class DescriptionSerializer extends StdSerializer<Description> {
    DescriptionSerializer() {
        super(Description.class);
    }

    @Override
    public void serialize(Description value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        if (value != null) {
            jgen.writeString(value.getDescription());
        } else {
            jgen.writeNull();
        }
    }
}

In a database, I have null in DESCRIPTION column of PRODUCT table

When I put breakpoint here:
https://github.com/spring-projects/spring-data-rest/blob/9b0f0c7101cf6e9b460f560901fe61ae11b69285/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryEntityController.java#L202

and inside:

protected Specification() {
        this.description = new Description(null);
}

I can see that JPA/Hibernate/Spring Data invokes this empty constructor and Description value object is initialized with {{null}, i.e. Description(null).

When I step forward and RepositoryInvoker finds all results using Pageable, description value object fields in Product entity are set to null instead of Description(null).

Why is that?
Is is possible to have it as I describe above?

The side effect of this is that my custom DescriptionSerializer
is never invoked because of how Jackson works internally, UnwrappingBeanPropertyWriter doesn't unwrap null value objects.

See here for the reference: https://github.com/FasterXML/jackson-databind/blob/master/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanPropertyWriter.java#L89

So to sum it up:
null value objects are not unwrapped properly using Jackson and I don't see expected JSON content:

{"description" : null}

what leads to inconsistent REST API where description is omitted completely.

Frontend clients written in React are sensitive to this behaviour.


No further details from DATAREST-1175

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.