Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I validate incoming JSON data inside a REST service?

Tags:

A rest service needs to validate all incoming json data against a json schema. The json schemas are public accessible and can be retrieved via http requests.

I'm using the jackson-framwork for marshaling and unmarshaling between java and json. So far I couldn't find any possibility to validate the data against the schema by using jackson.

I also tried the JsonTools framework which obviously comes up with such a validation functionality. But unfortunately it wasn't possible for me to get the validation to work. Why JsonTool schema validation isn't working?

How can I do such a validation?

like image 201
My-Name-Is Avatar asked Aug 09 '13 20:08

My-Name-Is


People also ask

How do I validate a JSON response?

The simplest way to check if JSON is valid is to load the JSON into a JObject or JArray and then use the IsValid(JToken, JsonSchema) method with the JSON Schema. To get validation error messages, use the IsValid(JToken, JsonSchema, IList<String> ) or Validate(JToken, JsonSchema, ValidationEventHandler) overloads.

Can we validate JSON with schema?

JSON Schema is a powerful tool. It enables you to validate your JSON structure and make sure it meets the required API. You can create a schema as complex and nested as you need, all you need are the requirements. You can add it to your code as an additional test or in run-time.

What is JSON validator?

JSON Validator verifies that your JavaScript Object Notation adheres to the JSON specification: www.json.org. JSON Validator also formats or humanizes your JSON to render it readable following common linting practices such as multi-line and indentation.


2 Answers

I searched for the best practice to enforce validation for incoming json data into a RESTful service. My suggestion is to use a MessageBodyReader which performs the validation inside the readFrom method. Below there is an message-body-reader example which is non-generic for the sake of simplicity.

I also was interesed in finding the best framework for doing json data validation. Because I use the jackson framework (version 1.8.5) for marshaling and unmarshaling between json and java, it would have been nice if this framework would provide a json data validation functionality. Unfortunately I couldn't find any possibility to do this with jackson. Finally I got it working with the json-schema-validator available at https://github.com. The version I use is 2.1.7

import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.annotation.Annotation; import java.lang.reflect.Type;  import javax.servlet.ServletContext; import javax.ws.rs.Consumes; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.Provider;  import org.codehaus.jackson.map.ObjectMapper;  import at.fhj.ase.dao.data.Address; import at.fhj.ase.xmlvalidation.msbreader.MessageBodyReaderValidationException;  import com.fasterxml.jackson.databind.JsonNode; import com.github.fge.jackson.JsonLoader; import com.github.fge.jsonschema.exceptions.ProcessingException; import com.github.fge.jsonschema.main.JsonSchemaFactory; import com.github.fge.jsonschema.main.JsonValidator; import com.github.fge.jsonschema.report.ProcessingReport;  @Provider @Consumes(MediaType.APPLICATION_JSON) public class AddressJsonValidationReader implements MessageBodyReader<Address> {      private final String jsonSchemaFileAsString;      public AddressJsonValidationReader(@Context ServletContext servletContext) {         this.jsonSchemaFileAsString = servletContext                 .getRealPath("/json/Address.json");     }      @Override     public boolean isReadable(Class<?> type, Type genericType,             Annotation[] annotations, MediaType mediaType) {         if (type == Address.class) {             return true;         }         return false;     }      @Override     public Address readFrom(Class<Address> type, Type genericType,             Annotation[] annotations, MediaType mediaType,             MultivaluedMap<String, String> httpHeaders, InputStream entityStream)             throws IOException, WebApplicationException {          final String jsonData = getStringFromInputStream(entityStream);         System.out.println(jsonData);          InputStream isSchema = new FileInputStream(jsonSchemaFileAsString);         String jsonSchema = getStringFromInputStream(isSchema);          /*          * Perform JSON data validation against schema          */         validateJsonData(jsonSchema, jsonData);          /*          * Convert stream to data entity          */         ObjectMapper m = new ObjectMapper();         Address addr = m.readValue(stringToStream(jsonData), Address.class);          return addr;     }      /**      * Validate the given JSON data against the given JSON schema      *       * @param jsonSchema      *            as String      * @param jsonData      *            as String      * @throws MessageBodyReaderValidationException      *             in case of an error during validation process      */     private void validateJsonData(final String jsonSchema, final String jsonData)             throws MessageBodyReaderValidationException {         try {             final JsonNode d = JsonLoader.fromString(jsonData);             final JsonNode s = JsonLoader.fromString(jsonSchema);              final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();             JsonValidator v = factory.getValidator();              ProcessingReport report = v.validate(s, d);             System.out.println(report);             if (!report.toString().contains("success")) {                 throw new MessageBodyReaderValidationException(                         report.toString());             }          } catch (IOException e) {             throw new MessageBodyReaderValidationException(                     "Failed to validate json data", e);         } catch (ProcessingException e) {             throw new MessageBodyReaderValidationException(                     "Failed to validate json data", e);         }     }      /**      * Taken from <a href=      * "http://www.mkyong.com/java/how-to-convert-inputstream-to-string-in-java/"      * >www.mkyong.com</a>      *       * @param is      *            {@link InputStream}      * @return Stream content as String      */     private String getStringFromInputStream(InputStream is) {         BufferedReader br = null;         StringBuilder sb = new StringBuilder();          String line;         try {              br = new BufferedReader(new InputStreamReader(is));             while ((line = br.readLine()) != null) {                 sb.append(line);             }          } catch (IOException e) {             e.printStackTrace();         } finally {             if (br != null) {                 try {                     br.close();                 } catch (IOException e) {                     e.printStackTrace();                 }             }         }          return sb.toString();     }      private InputStream stringToStream(final String str) throws UnsupportedEncodingException {         return new ByteArrayInputStream(str.getBytes("UTF-8"));     }  } 
like image 54
My-Name-Is Avatar answered Sep 19 '22 09:09

My-Name-Is


import com.github.fge.jsonschema.core.report.ProcessingReport; import com.github.fge.jsonschema.main.JsonSchema; import com.github.fge.jsonschema.main.JsonSchemaFactory; import com.github.fge.jackson.JsonLoader; import com.fasterxml.jackson.databind.JsonNode;  public class ValidationJSON {     public static void main(String[] arr){        String jsonData = "{\"name\": \"prem\"}";        String jsonSchema = ""; //Schema we can generate online using http://jsonschema.net/        final JsonNode data = JsonLoader.fromString(jsonData);        final JsonNode schema = JsonLoader.fromString(jsonSchema);         final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();        JsonValidator validator = factory.getValidator();         ProcessingReport report = validator.validate(schema, data);        System.out.println(report.isSuccess());     }  } 
like image 38
Premraj Avatar answered Sep 18 '22 09:09

Premraj