api-macro: make type optional in some cases

Objects and arrays are now optionally identified by their
'properties' or 'items' property if their 'type' is left
out.

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2019-11-26 13:27:53 +01:00
parent 5b41f68891
commit 7f7a9fe92f
2 changed files with 30 additions and 15 deletions

View File

@ -129,14 +129,6 @@ struct JSONObject {
pub elements: HashMap<SimpleIdent, JSONValue>,
}
//impl TryFrom<JSONValue> for JSONObject {
// type Error = syn::Error;
//
// fn try_from(value: JSONValue) -> Result<Self, syn::Error> {
// value.into_object()
// }
//}
impl Parse for JSONObject {
fn parse(input: ParseStream) -> syn::Result<Self> {
let content;
@ -157,15 +149,25 @@ impl Parse for JSONObject {
}
}
impl std::ops::Deref for JSONObject {
type Target = HashMap<SimpleIdent, JSONValue>;
fn deref(&self) -> &Self::Target {
&self.elements
}
}
impl std::ops::DerefMut for JSONObject {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.elements
}
}
impl JSONObject {
fn span(&self) -> Span {
self.brace_token.span
}
fn remove(&mut self, name: &str) -> Option<JSONValue> {
self.elements.remove(name)
}
fn remove_required_element(&mut self, name: &str) -> Result<JSONValue, syn::Error> {
self.remove(name)
.ok_or_else(|| format_err!(self.span(), "missing required element: {}", name))
@ -309,8 +311,23 @@ enum SchemaItem {
}
impl SchemaItem {
/// If there's a `type` specified, parse it as that type. Otherwise check for keys which
/// uniqueply identify the type, such as "properties" for type `Object`.
fn try_extract_from(obj: &mut JSONObject) -> Result<Self, syn::Error> {
match SimpleIdent::try_from(obj.remove_required_element("type")?)?.as_str() {
let ty = obj.remove("type").map(SimpleIdent::try_from).transpose()?;
let ty = match &ty {
Some(ty) => ty.as_str(),
None => {
if obj.contains_key("properties") {
"Object"
} else if obj.contains_key("items") {
"Array"
} else {
bail!(obj.span(), "failed to guess 'type' in schema definition");
}
}
};
match ty {
"Null" => Ok(SchemaItem::Null),
"Boolean" => Ok(SchemaItem::Boolean),
"Integer" => Ok(SchemaItem::Integer),

View File

@ -8,7 +8,6 @@ use serde_json::Value;
#[api]
#[input({
type: Object,
properties: {
username: {
type: String,
@ -22,7 +21,6 @@ use serde_json::Value;
}
})]
#[returns({
type: Object,
description: "Returns a ticket",
properties: {
"username": {