jss-core 0.2.0

Json Simplified Schema Core Interface
Documentation
use jsonschema::{Draft, JSONSchema};

use json_value::{to_string_pretty, JsonObject, JsonValue};

use crate::{JssError, JssSchema, JssType, JssValue, Result};

impl JssSchema {
    pub fn as_json_schema(&self) -> String {
        to_string_pretty(&JsonValue::from(self))
    }
    pub fn as_validator(&self) -> Result<JSONSchema> {
        let schema = JsonValue::from(self);
        let compiled = JSONSchema::options().with_draft(Draft::Draft7).compile(&schema)?;
        return Ok(compiled);
    }
    pub fn validate(&self, value: &JsonValue) -> Vec<JssError> {
        let mut out = vec![];
        let validator = match self.as_validator() {
            Ok(o) => o,
            Err(e) => {
                out.push(e);
                return out;
            }
        };
        match validator.validate(value) {
            Ok(_) => {}
            Err(e) => {
                for i in e {
                    out.push(JssError::from(i))
                }
            }
        }
        return out;
    }
    pub fn is_valid(&self, s: &JsonValue) -> bool {
        self.validate(s).is_empty()
    }
}

impl From<&JssSchema> for JsonValue {
    fn from(jss: &JssSchema) -> Self {
        if jss.is_anything() {
            return JsonValue::Bool(true);
        }
        if jss.is_noting() {
            return JsonValue::Bool(false);
        }
        let mut object = JsonObject::default();
        if jss.is_top() {
            object.insert("title".to_string(), jss.get_name().into());
        }
        match jss.is_ref_type() {
            true => object.insert("$ref".to_string(), jss.get_type().into()),
            false => object.insert("type".to_string(), jss.get_type().into()),
        };
        if jss.has_description() {
            object.insert("description".to_string(), jss.get_description().into());
        }
        for (k, v) in jss.attributes() {
            object.insert(k.into(), v.clone().into());
        }
        if jss.is_top() {
            let definitions: JsonObject = jss.definitions().map(|(k, v)| (k.clone(), v.into())).collect();
            object.insert("$defs".to_string(), definitions.into());
        }
        let properties: JsonObject = jss.properties().map(|(k, v)| (k.clone(), v.into())).collect();
        object.insert("properties".to_string(), properties.into());

        JsonValue::Object(object)
    }
}

impl From<JssValue> for JsonValue {
    fn from(jss: JssValue) -> Self {
        match jss {
            JssValue::Null => JsonValue::Null,
            JssValue::Boolean(v) => JsonValue::Bool(v),
            JssValue::Number(v) => JsonValue::Number(v),
            JssValue::String(v) => JsonValue::String(v),
            JssValue::Url(v) => JsonValue::String(v),
            JssValue::Regex(v) => JsonValue::String(v),
            JssValue::Array(v) => v.into_iter().map(JsonValue::from).collect(),
            JssValue::Object(v) => v.into_iter().map(|(k, v)| (k, JsonValue::from(v))).collect(),
        }
    }
}

impl From<JssType> for JsonValue {
    fn from(jss: JssType) -> Self {
        JsonValue::String(jss.to_string())
    }
}

impl From<&JssType> for JsonValue {
    fn from(jss: &JssType) -> Self {
        JsonValue::String(jss.to_string())
    }
}