Search code examples
javaweb-servicesjacksonjersey

Send empty JSON objet to API


For lab purpose I have to send a JSON object containing others objects and one of them has no property (empty) as you can see :

{
     "id": "00u12e3knx76B4PNS4x7",
     "scope": "USER",
     "credentials": {
     "userName": "some@email.com"
     },
     "profile": {}
}

I'm using Java Jersey and POJO to generate Java classes from JSON payloads but I cannot find what to send in this case match my API requirement.

Here is my code sample :

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response eventHook(String body, @HeaderParam("Pass") String password) {
    ObjectMapper objectMapper = new ObjectMapper();
    RequestPayload requestPayload = new RequestPayload();

    writeLogger(body);

    try {
        requestPayload = objectMapper.readValue(body, RequestPayload.class);
    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }

    EventsItem event = requestPayload.getData().getEvents().get(0);

    TargetItem targetItem = event.getTarget().get(2);

    RequestApiAssignUser user = new RequestApiAssignUser();

    Credentials credentials = new Credentials();
    credentials.setUserName("id");
    user.setId(getUser.getId());
    user.setScope("USER");
    user.setCredentials(credentials);

    Profile profile = new Profile();
    user.setProfile(profile);

    Response postResponse = ClientBuilder.newClient()
            .target(API_URL)
            .path("apps/" + getApps("0oa13t5dqnkYGDZEd4x7") + "/users")
            .request(MediaType.APPLICATION_JSON)
            .header(HttpHeaders.AUTHORIZATION, "SSWS " + API_TOKEN)
            .post(Entity.entity(user, MediaType.APPLICATION_JSON));

    String responseAPI = postResponse.readEntity(String.class);

    return Response.status(200).entity(responseAPI).build();

Here is the error due to the imposssibility to serialize Profile Object because it has no properties :

jakarta.ws.rs.ProcessingException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class Payload.Api.Apps.Post.Assign.Request.Profile and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: Payload.Api.Apps.Post.Assign.Request.RequestApiAssignUser["profile"])

Thanks !


Solution

  • The error is telling you to disable the SerializationFeature.FAIL_ON_EMPTY_BEANS property on the ObjectMapper. Normally to configure the ObjectMapper with Jersey, you would implement a ContextResolver. The the Jackson ObjectMapper that's used under the hood would look this resolver up and configure the property.

    But in this case, you already are using a mapper in your code. So I would just configure that mapper and then serialize the User object into a String and use that JSON string as the entity

    objectMapper.disable(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS);
    

    Then at the bottom before your client code just serialize the User to a string.

    String userJson = objectMapper.writeValueAsString(user);
    Response postResponse = ClientBuilder.newClient()
                ...
                .post(Entity.entity(userJson, MediaType.APPLICATION_JSON));
    

    In other cases, if you did not already have an ObjectMapper, you would implement a ContextResolver as I mentioned above.

    public class ObjectMapperResolver implements ContextResolver<ObjectMapper> {
    
        private final ObjectMapper mapper = new ObjectMapper();
    
        public ObjectMapperResolver() {
            mapper.disable(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS);
        }
    
        @Override
        public ObjectMapper getContext(Class<?> cls) {
            return mapper;
        }
    }
    

    Then you would register this with the client

    Response postResponse = ClientBuilder.newClient()
            .register(ObjectMapperResolver.class)
            ...