Trying to Validate JSON using Jackson through Spring Boot Rest
Solution 1
Figured it out!
Added the following changes:
Inside the @RequestMapping code section:
consumes = "text/plain",
produces = "application/json"
Changed @RequestBody from Map to String payload.
ValidationService class:
@RequestMapping(value="/validate",
method = RequestMethod.POST,
consumes="text/plain",
produces="application/json")
public ValidationResponse process(@RequestBody String payload) throws JsonParseException,
IOException {
ValidationResponse response = new ValidationResponse();
boolean retValue = false;
retValue = Validator.isValid(payload);
System.out.println(retValue);
if (retValue == false) {
response.setMessage("Invalid JSON");
}
else {
response.setMessage("Valid JSON");
}
return response;
}
Validator class:
import java.io.IOException;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Validator {
public static boolean isValid(String json) {
boolean retValue = true;
try {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
JsonFactory factory = mapper.getFactory();
JsonParser parser = factory.createParser(json);
JsonNode jsonObj = mapper.readTree(parser);
System.out.println(jsonObj.toString());
}
catch(JsonParseException jpe) {
retValue = false;
}
catch(IOException ioe) {
retValue = false;
}
return retValue;
}
}
ValidationResponse:
public class ValidationResponse {
public String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Using 'text/plain' for Content-type:
curl -H "Accept: application/json" -H "Content-type: text/plain" -X POST -d \
'{"name":"value"}' http://localhost:8080/myservice/validate
Now, everything works! This rocks!
Solution 2
After spring 3.2 you can use org.springframework.web.bind.annotation.ControllerAdvice to handle these kind of globally thrown exceptions. read more
Example code
@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<?> handleHttpMessageNotReadable(HttpMessageNotReadableException ex,
MultipleReadHttpRequest request) {
Map<String, String> errorResponse = new HashMap<>();
errorResponse.put("error", ex.getMessage());
errorResponse.put("code", "01");
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}
If there is a JSON format invalid error this method will be executed. You can customize your response.
PacificNW_Lover
Updated on June 07, 2022Comments
-
PacificNW_Lover about 2 years
Am trying to create a RESTful Web Service using Spring Boot which will take in a JSON and validate it using Jackson.
Here's the RESTful Web Service:
import java.util.Map; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.google.gson.Gson; @RestController @RequestMapping("/myservice") public class ValidationService { @RequestMapping(value="/validate", method = RequestMethod.POST) public void validate(@RequestBody Map<String, Object> payload) throws Exception { Gson gson = new Gson(); String json = gson.toJson(payload); System.out.println(json); boolean retValue = false; try { retValue = Validator.isValid(json); } catch(Throwable t) { t.printStackTrace(); } System.out.println(retValue); } }
Here's the code to the Validator:
import java.io.IOException; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; public class Validator { public static boolean isValid(String json) { boolean retValue = false; try { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY); JsonParser parser = objectMapper.getFactory().createParser(json); while (parser.nextToken() != null) {} retValue = true; objectMapper.readTree(json); }catch(JsonParseException jpe) { jpe.printStackTrace(); } catch(IOException ioe) { } return retValue; } }
So, when I use a curl to send a valid JSON:
curl -H "Accept: application/json" -H "Content-type: application/json" \ -X POST -d '{"name":"value"}' http://localhost:8080/myservice/validate
I receive the following to stdout:
{"name":"value"} true
But when use the following curl command for invalid JSON (deliberately removed the closing curly brace):
curl -H "Accept: application/json" -H "Content-type: application/json" \ -X POST -d '{"name":"value"' http://localhost:8080/myservice/validate
I receive the following inside stdout:
{"timestamp":1427698779063, "status":400,"error": "Bad Request", "exception":"org.springframework.http.converter.HttpMessageNotReadableException", "message":"Could not read JSON: Unexpected end-of-input: expected close marker for OBJECT (from [Source: java.io.PushbackInputStream@1edeb3e; line: 1, column: 0])\n at [Source: java.io.PushbackInputStream@1edeb3e; line: 1, column: 31]; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected end-of-input: expected close marker for OBJECT (from [Source: java.io.PushbackInputStream@1edeb3e; line: 1, column: 0])\n at [Source: java.io.PushbackInputStream@1edeb3e; line: 1, column: 31]", "path":"/myservice/validate"
Is there a way to ensure exception is handled on the server side but not thrown in stdout and then just have my code respond with:
false
Thanks for taking the time to read this...