81 lines
1.8 KiB
Plaintext
81 lines
1.8 KiB
Plaintext
///|
|
|
/// Create a schema that accepts a specific literal JSON value.
|
|
/// The value must match exactly (String, Number, Boolean, or Null).
|
|
///
|
|
/// # Example
|
|
/// ```mbt nocheck
|
|
/// let schema = @moon_zod.literal(Json::string("hello"))
|
|
/// schema.parse(Json::string("hello")) // Ok
|
|
/// schema.parse(Json::string("world")) // Err
|
|
/// ```
|
|
pub fn literal(
|
|
value : Json,
|
|
required_error? : String = "",
|
|
invalid_type_error? : String = "",
|
|
) -> Schema {
|
|
{
|
|
schema_type: LiteralType(value),
|
|
rules: [],
|
|
description: "",
|
|
required_error,
|
|
invalid_type_error,
|
|
name: "",
|
|
brand: "",
|
|
}
|
|
}
|
|
|
|
///|
|
|
pub fn Schema::parse_literal(
|
|
_self : Schema,
|
|
expected : Json,
|
|
json : Json,
|
|
path_stack : Array[String],
|
|
) -> RawSchemaResult {
|
|
let path = format_path(path_stack)
|
|
if json == expected {
|
|
Ok(json)
|
|
} else {
|
|
let default_msg = "Expected literal value \{json_to_literal_string(expected)}, got different value"
|
|
let message = if _self.invalid_type_error.is_empty() {
|
|
default_msg
|
|
} else {
|
|
_self.invalid_type_error
|
|
}
|
|
Err([
|
|
RawIssue::{
|
|
code: IssueCode::InvalidValue([expected]),
|
|
path,
|
|
message,
|
|
input: json,
|
|
},
|
|
])
|
|
}
|
|
}
|
|
|
|
///|
|
|
fn json_to_literal_string(json : Json) -> String {
|
|
match json {
|
|
String(s) => "\"" + s + "\""
|
|
Number(v, ..) =>
|
|
if v == v.to_int().to_double() {
|
|
v.to_int().to_string()
|
|
} else {
|
|
v.to_string()
|
|
}
|
|
True => "true"
|
|
False => "false"
|
|
Null => "null"
|
|
Array(arr) => {
|
|
let parts : Array[String] = arr.map(fn(v) { json_to_literal_string(v) })
|
|
"[" + parts.join(", ") + "]"
|
|
}
|
|
Object(map) => {
|
|
let pairs : Array[String] = []
|
|
for k, v in map {
|
|
pairs.push("\"" + k + "\": " + json_to_literal_string(v))
|
|
}
|
|
"{" + pairs.join(", ") + "}"
|
|
}
|
|
}
|
|
}
|