it-roy-ru.com

Java/Android - проверка строкового JSON по строковой схеме

У меня возникают проблемы с поиском наиболее простого способа проверки строки JSON по заданной строке JSON-схемы (для справки, это на Java, запущенное в приложении для Android). 

В идеале я хотел бы просто передать строку JSON и строку JSON-схемы, и она возвращает логическое значение относительно того, прошла ли она проверку. Благодаря поиску я нашел следующие 2 многообещающие библиотеки для достижения этой цели:

http://jsontools.berlios.de/

https://github.com/fge/json-schema-validator

Однако первый кажется довольно устаревшим с плохой поддержкой. Я внедрил библиотеку в свой проект, и даже с их JavaDocs я не смог сказать, как правильно построить объект «Validator» для проверки.

Аналогичная история со вторым, который, кажется, актуален с хорошим тестовым кодом. Однако то, что я хочу сделать, что очень просто, кажется немного пугающим и запутанным в том, как конкретно выполнить то, что я хочу (даже после просмотра ValidateServlet.Java file). 

Любопытно, есть ли у кого-нибудь еще какие-либо предложения о хорошем способе выполнения этой (из того, что кажется) простой задаче, или мне, возможно, нужно придерживаться второго варианта сверху? Заранее спасибо!

16
svguerin3

По сути, это то, что делает сервлет, с которым вы связаны, поэтому он может быть не однострочным, но все же выразительным.

useV4 и useId, как указано в сервлете, предназначены для указания параметров проверки для Default to draft v4 и Use id for addressing

Вы можете увидеть это онлайн: http://json-schema-validator.herokuapp.com/

public boolean validate(String jsonData, String jsonSchema, boolean useV4, boolean useId) throws Exception {
   // create the Json nodes for schema and data
   JsonNode schemaNode = JsonLoader.fromString(jsonSchema); // throws JsonProcessingException if error
   JsonNode data = JsonLoader.fromString(jsonData);         // same here

   JsonSchemaFactory factory = JsonSchemaFactories.withOptions(useV4, useId);
   // load the schema and validate
   JsonSchema schema = factory.fromSchema(schemaNode);
   ValidationReport report = schema.validate(data);

   return report.isSuccess();
}
10
Alex

Благодарю Дугласа Крокфорда и Фрэнсиса Галигу за то, что они написали процессор схемы json на основе Java! И он-лайн тестер в http://json-schema-validator.herokuapp.com/index.jsp это здорово! Мне действительно нравятся полезные сообщения об ошибках (я нашел только один пример, в котором они потерпели неудачу), хотя строка и столбец и/или контекст были бы еще лучше (прямо сейчас, вы получаете только информацию о строке и столбце во время ошибок формата JSON (любезно Джексона) Наконец, я хотел бы поблагодарить Майкла Дроетбоома за его учебник great (даже если он рассматривал только Python, Ruby и C, при этом явно игнорируя лучший из всех языков :-)).

Для тех, кто пропустил это (как я сделал сначала), есть примеры на github.com/fge/json-schema-processor-examples. Хотя эти примеры очень впечатляют, они не являются простыми примерами проверки json, которые изначально запрашивались (и которые я тоже искал). Простые примеры приведены по адресу github.com/fge/json-schema-validator/blob/master/src/main/Java/com/github/fge/jsonschema/examples/Example1.Java.

Код Алекса выше не работал для меня, но был очень полезен; мой pom вытягивает последнюю стабильную версию, 2.0.1 со следующей зависимостью, вставленной в мой файл maven pom.xml:

<dependency>
    <groupId>com.github.fge</groupId>
    <artifactId>json-schema-validator</artifactId>
    <version>2.0.1</version>
</dependency>

Тогда следующий код Java работает нормально для меня:

import Java.io.IOException;
import Java.util.Iterator;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonNode;
import com.github.fge.jsonschema.exceptions.ProcessingException;
import com.github.fge.jsonschema.main.JsonSchema;
import com.github.fge.jsonschema.main.JsonSchemaFactory;
import com.github.fge.jsonschema.report.ProcessingMessage;
import com.github.fge.jsonschema.report.ProcessingReport;
import com.github.fge.jsonschema.util.JsonLoader;


public class JsonValidationExample  
{

public boolean validate(String jsonData, String jsonSchema) {
    ProcessingReport report = null;
    boolean result = false;
    try {
        System.out.println("Applying schema: @<@<"+jsonSchema+">@>@ to data: #<#<"+jsonData+">#>#");
        JsonNode schemaNode = JsonLoader.fromString(jsonSchema);
        JsonNode data = JsonLoader.fromString(jsonData);         
        JsonSchemaFactory factory = JsonSchemaFactory.byDefault(); 
        JsonSchema schema = factory.getJsonSchema(schemaNode);
        report = schema.validate(data);
    } catch (JsonParseException jpex) {
        System.out.println("Error. Something went wrong trying to parse json data: #<#<"+jsonData+
                ">#># or json schema: @<@<"+jsonSchema+">@>@. Are the double quotes included? "+jpex.getMessage());
        //jpex.printStackTrace();
    } catch (ProcessingException pex) {  
        System.out.println("Error. Something went wrong trying to process json data: #<#<"+jsonData+
                ">#># with json schema: @<@<"+jsonSchema+">@>@ "+pex.getMessage());
        //pex.printStackTrace();
    } catch (IOException e) {
        System.out.println("Error. Something went wrong trying to read json data: #<#<"+jsonData+
                ">#># or json schema: @<@<"+jsonSchema+">@>@");
        //e.printStackTrace();
    }
    if (report != null) {
        Iterator<ProcessingMessage> iter = report.iterator();
        while (iter.hasNext()) {
            ProcessingMessage pm = iter.next();
            System.out.println("Processing Message: "+pm.getMessage());
        }
        result = report.isSuccess();
    }
    System.out.println(" Result=" +result);
    return result;
}

public static void main(String[] args)
{
    System.out.println( "Starting Json Validation." );
    JsonValidationExample app = new JsonValidationExample();
    String jsonData = "\"Redemption\"";
    String jsonSchema = "{ \"type\": \"string\", \"minLength\": 2, \"maxLength\": 11}";
    app.validate(jsonData, jsonSchema);
    jsonData = "Agony";  // Quotes not included
    app.validate(jsonData, jsonSchema);
    jsonData = "42";
    app.validate(jsonData, jsonSchema);
    jsonData = "\"A\"";
    app.validate(jsonData, jsonSchema);
    jsonData = "\"The pity of Bilbo may rule the fate of many.\"";
    app.validate(jsonData, jsonSchema);
}

}

Мой результат из приведенного выше кода:

Starting Json Validation.
Applying schema: @<@<{ "type": "string", "minLength": 2, "maxLength": 11}>@>@ to data: #<#<"Redemption">#>#
 Result=true
Applying schema: @<@<{ "type": "string", "minLength": 2, "maxLength": 11}>@>@ to data: #<#<Agony>#>#
Error. Something went wrong trying to parse json data: #<#<Agony>#># or json schema: @<@<{ "type": "string", "minLength": 2, "maxLength": 11}>@>@. Are the double quotes included?
 Result=false
Applying schema: @<@<{ "type": "string", "minLength": 2, "maxLength": 11}>@>@ to data: #<#<42>#>#
Processing Message: instance type does not match any allowed primitive type
 Result=false
Applying schema: @<@<{ "type": "string", "minLength": 2, "maxLength": 11}>@>@ to data: #<#<"A">#>#
Processing Message: string is too short
 Result=false
Applying schema: @<@<{ "type": "string", "minLength": 2, "maxLength": 11}>@>@ to data: #<#<"The pity of Bilbo may rule the fate of many.">#>#
Processing Message: string is too long
 Result=false

Наслаждайтесь!

13
Tihamer

@ Ответ Алекса сработал для меня на Android, но потребовал от меня Multi-dex и добавить:

    packagingOptions {
        pickFirst 'META-INF/ASL-2.0.txt'
        pickFirst 'draftv4/schema'
        pickFirst 'draftv3/schema'
        pickFirst 'META-INF/LICENSE'
        pickFirst 'META-INF/LGPL-3.0.txt'
    }

на мой build.gradle

2
HaydenKai