yoss
yoss

Reputation: 5

How do I differentiate between an optional value that was not passed and an explicit value in JSON?

I'm having problems differentiating between an optional value that was not passed and an explicit value in a JSON request.

The problem is that buildLevel and securityClass are defined as int fields in gmxClient.java, so when I POST a JSON object that does not contain one of the fields it is read as 0 and the value gets overwritten.

For example, if buildLevel = 3 and securityClass = 1 and this is my JSON request, securityClass gets overwritten as 0:

{
 "id"=00039281,
 "buildLevel"=5
}

Is there any way to get around this?

. . . .

gmxClientFacadeREST.java:

@POST
@Path("{clientId}")
@Consumes({MediaType.APPLICATION_JSON})
public Response editPost(@PathParam("clientId") Long clientId, gmxClient old) {
    try {
        gmxClient new = super.find(id);
        new.update(old);
        super.edit(new);
        return Response
                .status(Response.Status.OK)
                .build();
    }
    catch (Exception e) {
        return Response
                .status(Response.Status.BAD_REQUEST)
                .build();
    }
}

gmxClient.java:

public void update(gmxClient newEntity) {               
    if (newEntity.getBuildLevel() != null) setBuildLevel(newEntity.getBuildLevel()); // Throws exception, int will never be null
    
    if (newEntity.getSecurityClass() != null)   setSecurityClass(newEntity.getSecurityClass()); // Throws exception, int will never be null
}

Upvotes: 0

Views: 145

Answers (1)

Mirek Pluta
Mirek Pluta

Reputation: 8023

For reasons like this (and many others) it's good idea to have separate classes for a DTOs (used to contain data in transit - i.e. when sent to external service / to database / received through http request body) and separate classes used in the business logic in your application.

You face this problem because you used the same class for both a) http request body and b) business domain logic. Due to that your business model class gmxClient liminations (securityClass and other fields being primitives that can't express "lack of value") are also limiting your layer that integrates with "outside world" - in your case: your controller.

So, what I'd suggest you to do is to: create new class that will be used only within the controller (as request body), in this class you can use Integer, that will of course have a value of null when parsed from json - in case it doesn't exit. Then in the following logic you decide how to map it into your business model object.

Upvotes: 1

Related Questions