Skip to content

Commit 70e3a28

Browse files
skarimonkzou
andauthored
Add unparsedObject support (#33)
Co-authored-by: Kevin Zou <[email protected]>
1 parent 5d5cf00 commit 70e3a28

File tree

2,145 files changed

+133441
-6677
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

2,145 files changed

+133441
-6677
lines changed

.generator/src/generator/templates/common_mod.j2

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::error;
22
use std::fmt;
3+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
34

45
#[derive(Debug, Clone)]
56
pub struct ResponseContent<T> {
@@ -117,3 +118,26 @@ impl serde_json::ser::Formatter for DDFormatter {
117118
}
118119

119120
pub mod configuration;
121+
122+
#[derive(Clone, Debug, Eq, PartialEq)]
123+
pub struct UnparsedObject {
124+
pub value: serde_json::Value,
125+
}
126+
127+
impl<'de> Deserialize<'de> for UnparsedObject {
128+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
129+
where
130+
D: Deserializer<'de>,
131+
{
132+
let val: serde_json::Value = Deserialize::deserialize(deserializer)?;
133+
Ok(UnparsedObject {
134+
value: val,
135+
})
136+
}
137+
}
138+
139+
impl Serialize for UnparsedObject {
140+
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
141+
self.value.serialize(serializer)
142+
}
143+
}

.generator/src/generator/templates/model_enum.j2

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub enum {{ name }} {
1010
{%- for index, value in enumerate(model.enum) %}
1111
{{ model["x-enum-varnames"][index] or value.upper() }},
1212
{%- endfor %}
13+
UnparsedObject(crate::datadog::UnparsedObject),
1314
}
1415

1516
{%- if not model["type"] == "integer" %}
@@ -20,6 +21,7 @@ impl ToString for {{ name }} {
2021
{%- for index, value in enumerate(model.enum) %}
2122
Self::{{model["x-enum-varnames"][index] or value.upper()}} => String::from("{{value}}"),
2223
{%- endfor %}
24+
Self::UnparsedObject(v) => v.value.to_string(),
2325
}
2426
}
2527
}
@@ -31,6 +33,7 @@ impl Serialize for {{ name }} {
3133
S: Serializer,
3234
{
3335
match self {
36+
Self::UnparsedObject(v) => v.serialize(serializer),
3437
{%- if model["type"] == "string"%}
3538
_ => serializer.serialize_str(self.to_string().as_str()),
3639
{%- else %}
@@ -52,12 +55,7 @@ impl<'de> Deserialize<'de> for {{ name }} {
5255
{%- for index, value in enumerate(model.enum) %}
5356
{%- if model["type"] == "string" %}"{%- endif %}{{ value }}{%- if model["type"] == "string" %}"{%- endif %} => Self::{{ model["x-enum-varnames"][index] or value.upper() }},
5457
{%- endfor %}
55-
_ => {
56-
return Err(serde::de::Error::custom(format!(
57-
"Invalid value for SyntheticsDeviceID: {}",
58-
s
59-
)))
60-
}
58+
_ => Self::UnparsedObject(crate::datadog::UnparsedObject { value: serde_json::Value::{%- if model["type"] == "string" %}String{%- else %}Number{%- endif %}(s.into()) }),
6159
})
6260
}
6361
}

.generator/src/generator/templates/model_oneof.j2

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use serde::{Deserialize, Serialize};
1+
use serde::{Deserializer, Deserialize, Serialize};
22

33
{{ model.description | block_comment }}
44
#[non_exhaustive]
5-
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
5+
#[derive(Clone, Debug, PartialEq, Serialize)]
66
#[serde(untagged)]
77
pub enum {{name}} {
88
{%- for oneOf in model.oneOf %}
@@ -14,4 +14,34 @@ pub enum {{name}} {
1414
{{attributeName}}(Box<{{dataType}}>),
1515
{%- endif %}
1616
{%- endfor%}
17+
UnparsedObject(crate::datadog::UnparsedObject),
1718
}
19+
20+
impl<'de> Deserialize<'de> for {{ name }} {
21+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
22+
where
23+
D: Deserializer<'de>,
24+
{
25+
let value: serde_json::Value = Deserialize::deserialize(deserializer)?;
26+
27+
{%- for oneOf in model.oneOf %}
28+
{%- set dataType = get_type(oneOf, render_nullable=false, render_option=false, render_box=false, version=version) %}
29+
{%- set attributeName = (get_name(oneOf) or dataType)|upperfirst %}
30+
31+
{%- if oneOf | is_primitive or oneOf.type == "array" %}
32+
if let Ok(_v) = serde_json::from_value::<{{ dataType }}>(value.clone()) {
33+
return Ok({{ name }}::{{ attributeName }}(_v))
34+
}
35+
{%- else %}
36+
if let Ok(_v) = serde_json::from_value::<Box<{{ dataType }}>>(value.clone()) {
37+
if !_v._unparsed {
38+
return Ok({{ name }}::{{ attributeName }}(_v));
39+
}
40+
}
41+
{%- endif %}
42+
43+
{%- endfor%}
44+
45+
return Ok({{ name }}::UnparsedObject(crate::datadog::UnparsedObject { value }));
46+
}
47+
}

.generator/src/generator/templates/model_simple.j2

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
use serde::{Serialize, Deserialize};
1+
use std::fmt::{self, Formatter};
2+
use serde::{Deserializer, Deserialize, Serialize};
3+
use serde::de::{Error, MapAccess, Visitor};
24
use serde_with::skip_serializing_none;
35

46
{{ model.description | block_comment }}
57
#[non_exhaustive]
68
#[skip_serializing_none]
7-
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
9+
#[derive(Clone, Debug, PartialEq, Serialize)]
810
pub struct {{ name }} {
911
{%- for attr, schema in model.get("properties", {}).items() %}
1012
{%- set propertyName = attr|variable_name %}
@@ -28,6 +30,9 @@ pub struct {{ name }} {
2830
#[serde(flatten)]
2931
pub additional_properties: std::collections::BTreeMap<String, {{ dataType }}>,
3032
{%- endif %}
33+
#[serde(skip)]
34+
#[serde(default)]
35+
pub(crate) _unparsed: bool
3136
}
3237

3338
impl {{ name }} {
@@ -49,6 +54,7 @@ impl {{ name }} {
4954
{%- if model.additionalProperties is defined and model.additionalProperties != false %}
5055
additional_properties: std::collections::BTreeMap::new(),
5156
{%- endif %}
57+
_unparsed: false,
5258
}
5359
}
5460
{% for attr, schema in model.get("properties", {}).items() if attr not in model.required %}
@@ -78,3 +84,98 @@ impl Default for {{ name }} {
7884
}
7985
}
8086
{%- endif %}
87+
88+
impl<'de> Deserialize<'de> for {{ name }} {
89+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
90+
where
91+
D: Deserializer<'de>,
92+
{
93+
struct {{ name }}Visitor;
94+
impl<'a> Visitor<'a> for {{ name }}Visitor {
95+
type Value = {{ name }};
96+
97+
fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
98+
f.write_str("a mapping")
99+
}
100+
101+
fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
102+
where
103+
M: MapAccess<'a>,
104+
{
105+
{%- for attr, schema in model.get("properties", {}).items() %}
106+
{%- set required = attr in model.required %}
107+
{%- set propertyName = attr|variable_name %}
108+
{%- set nullable = schema.get("nullable", false)%}
109+
{%- set dataType = get_type(schema, alternative_name=name + attr|variable_name, render_nullable=nullable, render_option=not required, render_box=false, version=version) %}
110+
let mut {{ propertyName }}: {% if required %}Option<{% endif %}{{ dataType }}{% if required %}>{% endif %} = None;
111+
{%- endfor %}
112+
113+
{%- if model.additionalProperties is defined and model.additionalProperties != false %}
114+
{%- set dataType = get_type(model.additionalProperties, alternative_name=None, render_nullable=false, render_option=false, render_box=false, version=version) %}
115+
let mut additional_properties: std::collections::BTreeMap<String, {{ dataType }}> = std::collections::BTreeMap::new();
116+
{%- endif %}
117+
let mut _unparsed = false;
118+
119+
while let Some((k, v)) = map.next_entry::<String, serde_json::Value>()? {
120+
match k.as_str() {
121+
{%- for attr, schema in model.get("properties", {}).items() %}
122+
{%- set required = attr in model.required %}
123+
{%- set propertyName = attr|variable_name %}
124+
{%- set nullable = schema.get("nullable", false)%}
125+
{%- set dataType = get_type(schema, alternative_name=name + propertyName, render_option=false, version=version) %}
126+
"{{ attr }}" => {
127+
{%- if not nullable and not required %}
128+
if v.is_null() {
129+
continue;
130+
}
131+
{%- endif %}
132+
{{ propertyName }} = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
133+
{%- if schema.enum or schema.oneOf %}
134+
if let Some(ref _{{ propertyName }}) = {{ propertyName }} {
135+
match _{{ propertyName }} {
136+
{% if nullable%}Some({% endif %}{{ dataType }}::UnparsedObject(_{{ propertyName }}){% if nullable%}){% endif %} => {
137+
_unparsed = true;
138+
},
139+
_ => {}
140+
}
141+
}
142+
{%- endif %}
143+
},
144+
{%- endfor %}
145+
&_ => {
146+
{%- if model.additionalProperties is defined and model.additionalProperties != false %}
147+
if let Ok(value) = serde_json::from_value(v.clone()) {
148+
additional_properties.insert(k, value);
149+
}
150+
{%- endif %}
151+
},
152+
}
153+
}
154+
155+
{%- for attr, schema in model.get("properties", {}).items() %}
156+
{%- set required = attr in model.required %}
157+
{%- set propertyName = attr|variable_name %}
158+
{%- set nullable = schema.get("nullable", false)%}
159+
{%- if required %}
160+
let {{ propertyName }} = {{ propertyName }}.ok_or_else(|| M::Error::missing_field("{{ propertyName }}"))?;
161+
{%- endif %}
162+
{%- endfor %}
163+
164+
let content = {{ name }} {
165+
{%- for attr, schema in model.get("properties", {}).items() %}
166+
{%- set propertyName = attr|variable_name %}
167+
{{ propertyName }},
168+
{%- endfor %}
169+
{%- if model.additionalProperties is defined and model.additionalProperties != false %}
170+
additional_properties,
171+
{%- endif %}
172+
_unparsed,
173+
};
174+
175+
Ok(content)
176+
}
177+
}
178+
179+
deserializer.deserialize_any({{ name }}Visitor)
180+
}
181+
}

src/datadog/mod.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
12
use std::error;
23
use std::fmt;
34

@@ -121,3 +122,24 @@ impl serde_json::ser::Formatter for DDFormatter {
121122
}
122123

123124
pub mod configuration;
125+
126+
#[derive(Clone, Debug, Eq, PartialEq)]
127+
pub struct UnparsedObject {
128+
pub value: serde_json::Value,
129+
}
130+
131+
impl<'de> Deserialize<'de> for UnparsedObject {
132+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
133+
where
134+
D: Deserializer<'de>,
135+
{
136+
let val: serde_json::Value = Deserialize::deserialize(deserializer)?;
137+
Ok(UnparsedObject { value: val })
138+
}
139+
}
140+
141+
impl Serialize for UnparsedObject {
142+
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
143+
self.value.serialize(serializer)
144+
}
145+
}

src/datadogV1/model/model_access_role.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub enum AccessRole {
1111
ADMIN,
1212
READ_ONLY,
1313
ERROR,
14+
UnparsedObject(crate::datadog::UnparsedObject),
1415
}
1516

1617
impl ToString for AccessRole {
@@ -20,6 +21,7 @@ impl ToString for AccessRole {
2021
Self::ADMIN => String::from("adm"),
2122
Self::READ_ONLY => String::from("ro"),
2223
Self::ERROR => String::from("ERROR"),
24+
Self::UnparsedObject(v) => v.value.to_string(),
2325
}
2426
}
2527
}
@@ -30,6 +32,7 @@ impl Serialize for AccessRole {
3032
S: Serializer,
3133
{
3234
match self {
35+
Self::UnparsedObject(v) => v.serialize(serializer),
3336
_ => serializer.serialize_str(self.to_string().as_str()),
3437
}
3538
}
@@ -46,12 +49,9 @@ impl<'de> Deserialize<'de> for AccessRole {
4649
"adm" => Self::ADMIN,
4750
"ro" => Self::READ_ONLY,
4851
"ERROR" => Self::ERROR,
49-
_ => {
50-
return Err(serde::de::Error::custom(format!(
51-
"Invalid value for SyntheticsDeviceID: {}",
52-
s
53-
)))
54-
}
52+
_ => Self::UnparsedObject(crate::datadog::UnparsedObject {
53+
value: serde_json::Value::String(s.into()),
54+
}),
5555
})
5656
}
5757
}

0 commit comments

Comments
 (0)