Search code examples
javagsonlomboknotnull

Prevent false positve null warnings from IDE with gson and notNull annoation


I have a simple json object.

{"id": 1, "name": "John"}

My class for reading this object is the following.

@Getter
public class Foo {
    
    @Setter
    private long id;
    
    @NotNull
    private String name;
}

I am using lombok for generating the getters and annotating not-null fields with jetbrain's @NotNull annotation.

String json = "{\"id\": 1, \"name\": \"John\"}";

Foo foo = new Gson().fromJson(json, Foo.class);
foo.setId(42);

Reading the json works just fine.

The only problem that I have that I am getting an error from the IDE Not-null fields must be initialized from my name field.

It is technically correct, my name field is not initalized in the constructor.

However, I am using Gson to deserialize my object and know that name is never null. I do not want to create a normal object, just read from json.

Also I need the annotation @NotNull, because lomboks @Getter will generate me a getter with an @NotNull annotation.

I also have some cases where I want to replace one of my field (id) with another value.

I do not want to use a plain Java getter or remove the annoation from my attribute.

What can I do?


Solution

  • This solution works with Java 14 or higher.

    One possible way is using a record. Instead of writing a class and generating the getter via lombok, it is also possible to do this:

    public record Foo(int id, @NotNull String name) { 
    }
    

    It will automatically generate a method name() which has the @NotNull annotation.

    If you later need to set a field of a record, you need to follow this solution and do something like this:

    public record Foo(int id, @NotNull String name) {
        
        @NotNull
        public Foo withId(int id) {
            return new Foo(id, name());
        }
    
    }
    

    This will allow to modify the id later. Only disadvantage is that you need to type out the method to set the field (withId) and that you have a new record that you need to handle correctly.

    Foo foo = new Gson().fromJson(json, Foo .class);
    foo = foo.withId(42);