Skip to content

Commit

Permalink
Add partial serde attribute support
Browse files Browse the repository at this point in the history
* Add partial serde attribute support for Components. This allows use of serde's skip and rename on fields and variants and rename_all on container level.
  • Loading branch information
juhaku committed Apr 27, 2022
1 parent 80b64d9 commit d96ce93
Show file tree
Hide file tree
Showing 6 changed files with 536 additions and 60 deletions.
77 changes: 76 additions & 1 deletion tests/component_derive_test.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#![cfg(feature = "serde_json")]
use std::{borrow::Cow, cell::RefCell, collections::HashMap, vec};
use std::{borrow::Cow, cell::RefCell, collections::HashMap, marker::PhantomData, vec};

#[cfg(any(feature = "chrono_types", feature = "chrono_types_with_format"))]
use chrono::{Date, DateTime, Duration, Utc};

use serde::Serialize;
use serde_json::Value;
use utoipa::{Component, OpenApi};

Expand Down Expand Up @@ -796,3 +797,77 @@ fn derive_struct_with_uuid_type() {
"properties.id.format" = r#""uuid""#, "Post id format"
}
}

#[test]
fn derive_parse_serde_field_attributes() {
struct S;
let post = api_doc! {
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct Post<S> {
#[serde(rename = "uuid")]
id: String,
#[serde(skip)]
_p: PhantomData<S>,
long_field_num: i64,
}
};

assert_value! {post=>
"properties.uuid.type" = r#""string""#, "Post id type"
"properties.longFieldNum.type" = r#""integer""#, "Post long_field_num type"
"properties.longFieldNum.format" = r#""int64""#, "Post logn_field_num format"
}
}

#[test]
fn derive_parse_serde_simple_enum_attributes() {
let value = api_doc! {
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
enum Value {
A,
B,
#[serde(skip)]
C,
}
};

assert_value! {value=>
"enum" = r#"["a","b"]"#, "Value enum variants"
}
}

#[test]
fn derive_parse_serde_complex_enum() {
#[derive(Serialize)]
struct Foo;
let complex_enum = api_doc! {
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
enum Bar {
UnitValue,
#[serde(rename_all = "camelCase")]
NamedFields {
#[serde(rename = "id")]
named_id: &'static str,
name_list: Option<Vec<String>>
},
UnnamedFields(Foo),
#[serde(skip)]
Random,
}
};

assert_value! {complex_enum=>
"oneOf.[0].enum" = r#"["unitValue"]"#, "Unit value enum"
"oneOf.[0].type" = r#""string""#, "Unit value type"

"oneOf.[1].properties.namedFields.properties.id.type" = r#""string""#, "Named fields id type"
"oneOf.[1].properties.namedFields.properties.nameList.type" = r#""array""#, "Named fields nameList type"
"oneOf.[1].properties.namedFields.properties.nameList.items.type" = r#""string""#, "Named fields nameList items type"
"oneOf.[1].properties.namedFields.required" = r#"["id"]"#, "Named fields required"

"oneOf.[2].properties.unnamedFields.$ref" = r###""#/components/schemas/Foo""###, "Unnamed fields ref"
}
}
10 changes: 10 additions & 0 deletions utoipa-gen/src/doc_comment.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::ops::Deref;

use proc_macro2::{Ident, Span};
use proc_macro_error::{abort_call_site, emit_warning, ResultExt};
use syn::{Attribute, Lit, Meta};
Expand Down Expand Up @@ -54,3 +56,11 @@ impl CommentAttributes {
}
}
}

impl Deref for CommentAttributes {
type Target = Vec<String>;

fn deref(&self) -> &Self::Target {
&self.0
}
}
15 changes: 14 additions & 1 deletion utoipa-gen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#![warn(missing_docs)]
#![warn(rustdoc::broken_intra_doc_links)]

use std::{borrow::Cow, mem};
use std::{borrow::Cow, mem, ops::Deref};

use doc_comment::CommentAttributes;
use schema::component::Component;
Expand Down Expand Up @@ -825,6 +825,19 @@ where
}
}

impl<T> Deref for Array<T>
where
T: Sized + ToTokens,
{
type Target = Vec<T>;

fn deref(&self) -> &Self::Target {
match self {
Self::Owned(vec) => vec,
}
}
}

impl<T> ToTokens for Array<T>
where
T: Sized + ToTokens,
Expand Down
Loading

0 comments on commit d96ce93

Please sign in to comment.