3

I'm in the process of developing a RESTful API. I want to get user details by calling API. But my expected response not included null values.

Expected Response

{
    "id": 1,
    "username": "admin",
    "fullName": "Geeth Gamage",
    "userRole": "ADMIN",
    "empNo": null
} 

Actual Response

  {
        "id": 1,
        "username": "admin",
        "fullName": "Geeth Gamage",
        "userRole": "ADMIN"
    } 

My Spring boot rest API code is below. why not include null parameters for my response?

@GetMapping(value = "/{userCode}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> findUser(@PathVariable String userCode)
{
    return ResponseEntity.status(HttpStatus.OK).body(userService.getUserByUserName(userCode));
}


@Override
@Transactional
public Object getUserByUserName(String username)
{
    try {
        User user = Optional.ofNullable(userRepository.findByUsername(username))
                   .orElseThrow(() -> new ObjectNotFoundException("User Not Found"));
            
            return new ModelMapper().map(user, UserDTO.class);

    } catch (ObjectNotFoundException ex) {
        log.error("Exception  :  ", ex);
        throw ex;
    } catch (Exception ex) {
        log.error("Exception  :  ", ex);
        throw ex;
    }
}

User entity class and UserDTO object class as below

User.class

@Data
@Entity
@Table(name = "user")
public class User{
    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "ID", unique = true, nullable = false)
    private Long id;
    @Column(name = "USERNAME", nullable = false, length = 64)
    private String username;
    @Column(name = "USER_ROLE", nullable = false)
    private String userRole;
    @Column(name = "EMP_NO")
    private String empNo;
}

UserDTO.class

@Data
public class  UserDTO {
    private Long id;
    private String username;
    private String fullName;
    private String userRole;
    private String empNo;
}

2 Answers 2

2

Assuming you are using Jackson you can configure its global behaviour using setSerializationInclusion(JsonInclude.Include) on the ObjectMapper.

For your use case you can configure it as NON_EMPTY or ALWAYS. For more details please check https://fasterxml.github.io/jackson-annotations/javadoc/2.6/com/fasterxml/jackson/annotation/JsonInclude.Include.html.

You can also do this at class or attribute level using the corresponding annotation @JsonInclude.

Sign up to request clarification or add additional context in comments.

2 Comments

how to do it at the project level?
Use setSerializationInclusion(JsonInclude.Include) on the ObjectMapper that you should configure in a configuration class.
0

I did was Jao Dias mentions: setSerializationInclusion at project level. So, to get my Rest API responses to show fields as null (that were being ommitted during jackson serialization), first two did not work i.e yaml file and registering a bean did not work.

 spring:
        profiles: local        
         jackson.default-property-inclusion: always

even added a configuration bean

@Bean
    public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {

        return builder -> builder.serializationInclusion(JsonInclude.Include.ALWAYS);
    }

I suppose as the issue is of RequestMappingHandler for me and not Jackson serializationin general, I had to do a work around and register this during the spring container setup.

    @Component
public class JacksonFix {
    private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
    

    @PostConstruct
    public void init() {
        List<HttpMessageConverter<?>> messageConverters = requestMappingHandlerAdapter.getMessageConverters();
        for (HttpMessageConverter<?> messageConverter : messageConverters) {
            if (messageConverter instanceof MappingJackson2HttpMessageConverter) {
                MappingJackson2HttpMessageConverter m = (MappingJackson2HttpMessageConverter) messageConverter;
        m.getObjectMapper().setSerializationInclusion(JsonInclude.Include.ALWAYS);
                
            }
        }
    }

    private JacksonFix() {
        new AssertionError("instantiation of this class not allowed");
    }

    
    @Autowired
    public void setAnnotationMethodHandlerAdapter(RequestMappingHandlerAdapter requestMappingHandlerAdapter) {
        this.requestMappingHandlerAdapter  = requestMappingHandlerAdapter;
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.