2013-08-09 3 views
13

Служба отдыха должна проверять все входящие json-данные на json-схему. Схемы json являются общедоступными и могут быть получены через HTTP-запросы.Как проверить входящие данные JSON внутри службы REST?

Я использую каркас джексона для маршалинга и разборки между java и json. До сих пор я не мог найти никакой возможности проверить данные по схеме с помощью джексона.

Я также попробовал фреймворк JsonTools, который, очевидно, имеет такую ​​функцию проверки. Но, к сожалению, мне не удалось заставить валидацию работать. Why JsonTool schema validation isn't working?

Как я могу сделать такую ​​проверку?

+0

Дубликат http://stackoverflow.com/questions/2499126/json-schema-validation-using-java? – condit

+0

Наконец, я выяснил, как выполнить проверку json для служб REST. Я отправлю полный пример в качестве ответа, как только этот вопрос больше не будет 'на удержании' –

+0

Привет. FYI, пустые голоса будут связаны с тем, что stackoverflow не считается лучшим форумом для вопросов, основанных на мнениях, таких как лучшая библиотека для работы с X. Ознакомьтесь с [секцией помощи] (http://stackoverflow.com/help/dont -ask) – theon

ответ

12

Я искал наилучшую практику для обеспечения проверки правильности ввода входящих данных json в службу RESTful. Мое предложение состоит в том, чтобы использовать MessageBodyReader, который выполняет проверку внутри метода readFrom. Ниже приведен пример сообщения-тела-читателя, который является неэквивалентным для простоты.

Я также интересовался поиском наилучшего фреймворка для проверки данных json. Поскольку я использую фреймворк jackson (версия 1.8.5) для маршалинга и размаширования между json и java, было бы неплохо, если бы эта инфраструктура обеспечивала функциональность проверки данных json. К сожалению, я не мог найти никакой возможности сделать это с Джексоном. Наконец, я получил его с помощью json-schema-validator доступен по адресу https://github.com. Версия я использую 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")); 
    } 

} 
6
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(Stirng[] arr){ 
     String jsonData="{\"name\": \"prem\"}"; 
     String jsonSchema=""; //Schema we can genearte 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()); 
    } 

}