hilla icon indicating copy to clipboard operation
hilla copied to clipboard

@JsonProperty does not work as documented

Open vlukashov opened this issue 4 years ago • 4 comments

The current documentation for the @JsonProperty annotation is misleading: in reality it seem to have no effect on the TypeScript type generator (as of Vaadin 15.0.4).

  1. After reading the docs I would expect that @JsonProperty("bookId") private String id; in Java would lead to bookId: string; in TypeScript. This is not the case; the generated TS type has id: string.
  2. After reading the docs I would expect that
     public class Student {
       // NOTE: no field, only getter and setter
    
       @JsonProperty("name")
       public void setFirstName(String name) {
          this.name = name;
       }
    
       @JsonProperty("name")
       public String getFirstName() {
          return name;
       }
     }
    
    would lead to name: string; in TypeScript. This is not the case; the generated TS type has neither name nor firstName property at all.

The @JsonProperty annotation

It is used to define a method as a "setter" or "getter" for a logical property, or to define a field for being serialized and deserialized as a specific logical property.

The annotation value indicates the name of the property in the JSON object, by default it takes the java name of the method or field.

public class Student {
  @JsonProperty("bookId")
  private String id;
  private String name;

  @JsonProperty("name")
  public void setFirstName(String name) {
     this.name = name;
  }

  @JsonProperty("name")
  public String getFirstName() {
     return name;
  }

  @JsonProperty
  public int getRating() {
     return StudentRating.getRatingFor(name);
  }
}

vlukashov avatar Apr 15 '20 10:04 vlukashov

This seems to be a regression in 15.0.4. Now it should work again in 15.0.5, can you help to verify? @vlukashov

haijian-vaadin avatar Apr 20 '20 09:04 haijian-vaadin

I can still see the following issues when testing with 17.0-SNAPSHOT / 3.2-SNAPSHOT:

  1. @JsonProperty on a field is ignored:
    public static class Book {
        @JsonProperty("bookId")
        private String id;
    }
    
    should produce
    interface Book {
      bookId: string;
    }
    
    but produces
    interface Book {
      id: string;
    }
    
    which does not match the JSON object sent over the wire:
    {
      "bookId": null
    }
    
  2. Getters and setters are ignored:
    public static class Student {
        @JsonIgnore
        private String id;
    
        public void setStudentId(String id) {
            this.id = id;
        }
    
        public String getStudentId() {
            return id;
        }
    }
    
    should produce
    interface Student {
      studentId: string;
    }
    
    but produces
    interface Student {
    }
    
    which does not match the JSON object sent over the wire:
    {
      "studentId": null
    }
    
  3. @JsonProperty on a getters / setters is ignored:
    public static class Course {
        @JsonIgnore
        private String id;
    
        @JsonProperty("courseId")
        public void setId(String id) {
            this.id = id;
        }
    
        @JsonProperty("courseId")
        public String getId() {
            return id;
        }
    }
    
    should produce
    interface Course {
      courseId: string;
    }
    
    but produces
    interface Course {
    }
    
    which does not match the JSON object sent over the wire:
    {
      "courseId": null
    }
    
  4. The built-in nullability checker on Vaadin endpoints fails to detect the (unexpected) null property values returned by the backend in all the cases above. However, if @JsonIgnore is removed from private String id in the case 3, then the null checker actually does throw a server-side exception, as expected:
    2020-04-27 18:18:08.887 ERROR 32625 --- [nio-8080-exec-9] c.v.f.s.connect.VaadinConnectController  : Unexpected return value in endpoint 'RequestEndpoint' method 'getCourse'. Unexpected null value in Java Bean type 'com.example.demo.backend.RequestEndpoint$Course' property 'id'. Got null value for type 'java.lang.String', which is neither Optional nor void
    

vlukashov avatar Apr 27 '20 15:04 vlukashov

Any news about this? It's still broken in V20.

Should we at least update the documentation?

jcgueriaud1 avatar May 19 '21 08:05 jcgueriaud1

Please update documentation. Currently it is very misleading

vladislav-og avatar Jun 08 '21 18:06 vladislav-og