skip to Main Content

I have this code that runs on Tomee with Jakarta EE 9.1, it is supposed to generate a JSON string taking the data from inputObj. Problem is that there are fields with null values that are omitted from the resulting JSON even though withNullValues is set to true. Any ideas what could be wrong?

JsonbConfig config = new JsonbConfig().withNullValues(true);
                    
String json;
try (Jsonb jsonb = JsonbBuilder.create(config)) {
    json = jsonb.toJson(inputObj);
}

3

Answers


  1. Is it possible there are annotations on the fields of inputObj you are serializing that are overriding the .withNullValues(true) setting?

    Ref: https://jakarta.ee/specifications/jsonb/3.0/jakarta-jsonb-spec-3.0.html#customizing-null-handling

    I also found this: https://github.com/jakartaee/jsonb-api/issues/169#issuecomment-525387593

    You didn’t share the class for inputObj but it seems to me like the only way this won’t work is if there are annotations on the fields in the class overriding the global setting in config.

    Login or Signup to reply.
  2. I don’t know your full code, so this is my guess. If you don’t declare getter method for properties in class, Json-B skips to serialize fields. Here is my example.

    Without Getter

    package action.in.blog;
    
    import jakarta.json.bind.Jsonb;
    import jakarta.json.bind.JsonbBuilder;
    import jakarta.json.bind.JsonbConfig;
    import org.junit.jupiter.api.Test;
    
    public class JsonbTest {
    
        @Test
        void test() throws Exception {
            JsonbConfig config = new JsonbConfig().withNullValues(true);
    
            Input inputObj = new Input();
    
            try (Jsonb jsonb = JsonbBuilder.create(config)) {
                System.out.println(jsonb.toJson(inputObj));
            }
        }
    
        public static class Input {
            private String value;
        }
    }
    

    Result when without getter

    {}
    

    With Getter

    package action.in.blog;
    
    import jakarta.json.bind.Jsonb;
    import jakarta.json.bind.JsonbBuilder;
    import jakarta.json.bind.JsonbConfig;
    import org.junit.jupiter.api.Test;
    
    public class JsonbTest {
    
        @Test
        void test() throws Exception {
            JsonbConfig config = new JsonbConfig().withNullValues(true);
    
            Input inputObj = new Input();
    
            try (Jsonb jsonb = JsonbBuilder.create(config)) {
                System.out.println(jsonb.toJson(inputObj));
            }
        }
    
        public static class Input {
            private String value;
    
            public String getValue() {
                return value;
            }
        }
    }
    

    Result when with getter

    {"value":null}
    

    With public keyword

    If you don’t use getter method for fields, fields should be public.

    package action.in.blog;
    
    import jakarta.json.bind.Jsonb;
    import jakarta.json.bind.JsonbBuilder;
    import jakarta.json.bind.JsonbConfig;
    import org.junit.jupiter.api.Test;
    
    public class JsonbTest {
    
        @Test
        void test() throws Exception {
            JsonbConfig config = new JsonbConfig().withNullValues(true);
    
            Input inputObj = new Input();
    
            try (Jsonb jsonb = JsonbBuilder.create(config)) {
                System.out.println(jsonb.toJson(inputObj));
            }
        }
    
        public static class Input {
            public String value;
        }
    }
    

    Result when with public

    {"value":null}
    

    I hope this is helpful for you.

    Login or Signup to reply.
  3. tl;dr; solved.


    After I had read from your following comment, I solved your issue.

    No, the only annotation is at the field name level
    @JsonbProperty("field_name"), and nothing at the class level.

    The annotation’s default nillable value is false . To accomplish your request you need to make it true as following.

    @JsonbProperty(value = "test", nillable = true)
    public String your_field_name;
    

    It yields something like {... your other json fields, "test":null}


    To begin, I have never used before this post JSON-B API. For you, I have installed it and its dependencies via its official webpage.

    I have started a simple console app and created pom.xml to leverage its Maven dependencies as written on the webpage.

    I think your problem is as to the versions either that of its dependencies or directly its own version.

    Don’t forget to reload project after changing any settings related to Maven.

    What my pom.xml includes is

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>groupId</groupId>
        <artifactId>RefUrself</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <properties>
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    
         <!-- ** The rest is for JSON-B API ** -->
    
        <repositories>
            <!-- Needed for JSON-B API -->
            <repository>
                <id>java.net-Public</id>
                <name>Maven Java Net Snapshots and Releases</name>
                <url>https://maven.java.net/content/groups/public/</url>
            </repository>
        </repositories>
    
        <dependencies>
            <dependency>
                <groupId>javax.json.bind</groupId>
                <artifactId>javax.json.bind-api</artifactId>
                <version>1.0</version>
            </dependency>
    
            <dependency>
                <groupId>org.eclipse</groupId>
                <artifactId>yasson</artifactId>
                <version>1.0</version>
            </dependency>
    
            <dependency>
                <groupId>org.glassfish</groupId>
                <artifactId>javax.json</artifactId>
                <version>1.1</version>
            </dependency>
        </dependencies>
        
    </project>
    

    And, when I run its official example which is Dog class in which I changed name of the dog to null, it works like a charm.

    Dog class

    public class Dog {
        public String name;
        public int age;
        public boolean bitable;
    }
    

    The Test class in which the program begins to run

    import javax.json.bind.Jsonb;
    import javax.json.bind.JsonbBuilder;
    import javax.json.bind.JsonbConfig;
    
    public class Test {
        // Create a dog instance
        public static void main(String[] args) {
            Dog dog = new Dog();
            dog.name = null; // --> null as you see
            dog.age = 4;
            dog.bitable = false;
    
            JsonbConfig config = new JsonbConfig().withNullValues(true);
            // Create Jsonb and serialize
            try (Jsonb jsonb = JsonbBuilder.create(config)) {
                String result = jsonb.toJson(dog);
                System.out.println(result);
                //{"age":4,"bitable":false,"name":null}
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
    

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search