Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I validate JSON using an existing schema file in Rust?

I'm trying to validate a JSON given a JSON file and a schema.

Schema:

{
    "Address":{
        "properties":{
            "City":{
                "type":"string"
            },
            "Country":{
                "type":"string"
            },
            "Street":{
                "type":"string"
            }
        },
        "type":"object"
    }
}

JSON:

{
    "Address":{
        "Street":"Downing Street 10",
        "City":"London",
        "Country":"Great Britain"
    }
}

My Rust file:

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
extern crate valico;

use std::fs::File;
use std::io::Read;
use serde_json::Value;

use valico::json_dsl;
use valico::json_schema;

fn main() {
    let mut schemaFile = File::open("src/schema.json").unwrap();
    let mut jsonSchemaString = String::new();
    schemaFile.read_to_string(&mut jsonSchemaString).unwrap();

    let json_v4_schema: Value = serde_json::from_str(&jsonSchemaString).unwrap();


    let state = jsonSchemaString.process(&mut json_v4_schema, &None); //this is wrong as jsonSchemaString is not a jsonDsl.

    println!("Is valid: {}", state.is_valid())

}

I'm trying to use valico for the JSON validation, but I cant figure out how to pass the schema against which the JSON has to be validated. I have seen examples where a JsonDsl is built using the valico builder, but how do I do it if I already have a JSON schema and I want to validate against that? Is there any other way that I can achieve this?

like image 817
leoOrion Avatar asked Jun 24 '17 06:06

leoOrion


People also ask

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.

How do I validate a JSON Schema file?

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.

What is the value of using JSON Schema for validation?

The primary strength of JSON Schema is that it generates clear, human- and machine-readable documentation. It's easy to accurately describe the structure of data in a way that developers can use for automated validation. This makes work easier for developers and testers, but the benefits go beyond productivity.

What is a 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.


1 Answers

Late to the party here, but in case anyone else is having trouble with this, below is a MVCE I've adjusted to using the schema and data you used as an example. I included the strings directly in the code for "simplicity", but you can just replace that with fs::File/io::Read operations you already had.

extern crate serde_json;
extern crate valico;

use serde_json::from_str;
use valico::json_schema;

fn main() {
    let s = from_str(r#"
    {
        "Address": {
            "Street":"Downing Street 10",
            "City":"London",
            "Country":"Great Britain"
        }
    }
    "#).unwrap();

    let j_schema = from_str(r#"
    {
        "type": "object",
        "properties": {
            "Address": {
                "type": "object",
                "properties": {
                    "Country": {
                        "type": "string"
                    },
                    "Street": {
                        "type": "string"
                    }
                },
                "required": ["Country", "Street"]
            }
        },
        "required": ["Address"]
    }
    "#).unwrap();

    let mut scope = json_schema::Scope::new();
    let r_schema = scope.compile_and_return(j_schema, true).ok().unwrap();

    println!("Is valid: {}", r_schema.validate(&s).is_valid())
}

Running this prints Is valid: true. Changing the "Address" to "Addresses" and running it again prints Is valid: false

Please note that I had to make some small adjustments to your schema. First, to verify that valico is validating it correctly I set required fields. Secondly, since the root object doesn't have a name (it's only {}) the "Address" would be a property of that root object.

So instead of

{
    "Address": {
        "properties": {
            ...

it is instead

{
    "type": "object",
    "properties": {
        "Address": {
            "type": "object",
                ....

Also, it seems like valico requires an older version of serde_json, so I added this as dependency in my Cargo.toml

serde_json = "0.8"
like image 141
bleakgadfly Avatar answered Nov 26 '22 12:11

bleakgadfly