[Core/Rust Server] Check references in additionalProperties correctly when checking freeForm status (#19605)

* Check references in additionalProperties correctly

Handle references in additionalProperties correctly when determining free-form status

* Update samples
This commit is contained in:
Richard Whitehouse
2024-09-22 17:19:27 +01:00
committed by GitHub
parent e1a1d7ab5a
commit 8821cf095e
16 changed files with 209 additions and 39 deletions

View File

@@ -2424,7 +2424,7 @@ public class DefaultCodegen implements CodegenConfig {
return schema.getFormat();
}
return "string";
} else if (ModelUtils.isFreeFormObject(schema)) {
} else if (ModelUtils.isFreeFormObject(schema, openAPI)) {
// Note: the value of a free-form object cannot be an arbitrary type. Per OAS specification,
// it must be a map of string to values.
return "object";
@@ -2833,7 +2833,7 @@ public class DefaultCodegen implements CodegenConfig {
if (ModelUtils.isMapSchema(schema)) {
// an object or anyType composed schema that has additionalProperties set
addAdditionPropertiesToCodeGenModel(m, schema);
} else if (ModelUtils.isFreeFormObject(schema)) {
} else if (ModelUtils.isFreeFormObject(schema, openAPI)) {
// non-composed object type with no properties + additionalProperties
// additionalProperties must be null, ObjectSchema, or empty Schema
addAdditionPropertiesToCodeGenModel(m, schema);
@@ -3039,7 +3039,7 @@ public class DefaultCodegen implements CodegenConfig {
m.isNullable = Boolean.TRUE;
}
m.setTypeProperties(schema);
m.setTypeProperties(schema, openAPI);
m.setFormat(schema.getFormat());
m.setComposedSchemas(getComposedSchemas(schema));
if (ModelUtils.isArraySchema(schema)) {
@@ -3698,7 +3698,7 @@ public class DefaultCodegen implements CodegenConfig {
}
protected void updatePropertyForObject(CodegenProperty property, Schema p) {
if (ModelUtils.isFreeFormObject(p)) {
if (ModelUtils.isFreeFormObject(p, openAPI)) {
// non-composed object type with no properties + additionalProperties
// additionalProperties must be null, ObjectSchema, or empty Schema
property.isFreeFormObject = true;
@@ -4022,7 +4022,7 @@ public class DefaultCodegen implements CodegenConfig {
property.datatypeWithEnum = property.dataType;
}
property.setTypeProperties(p);
property.setTypeProperties(p, openAPI);
property.setComposedSchemas(getComposedSchemas(p));
if (ModelUtils.isIntegerSchema(p)) { // integer type
updatePropertyForInteger(property, p);
@@ -4068,7 +4068,7 @@ public class DefaultCodegen implements CodegenConfig {
!ModelUtils.isComposedSchema(p) &&
p.getAdditionalProperties() == null && p.getNot() == null && p.getEnum() == null);
if (!ModelUtils.isArraySchema(p) && !ModelUtils.isMapSchema(p) && !ModelUtils.isFreeFormObject(p) && !isAnyTypeWithNothingElseSet) {
if (!ModelUtils.isArraySchema(p) && !ModelUtils.isMapSchema(p) && !ModelUtils.isFreeFormObject(p, openAPI) && !isAnyTypeWithNothingElseSet) {
/* schemas that are not Array, not ModelUtils.isMapSchema, not isFreeFormObject, not AnyType with nothing else set
* so primitive schemas int, str, number, referenced schemas, AnyType schemas with properties, enums, or composition
*/
@@ -4865,7 +4865,7 @@ public class DefaultCodegen implements CodegenConfig {
}
}
r.setTypeProperties(responseSchema);
r.setTypeProperties(responseSchema, openAPI);
r.setComposedSchemas(getComposedSchemas(responseSchema));
if (ModelUtils.isArraySchema(responseSchema)) {
r.simpleType = false;
@@ -4925,7 +4925,7 @@ public class DefaultCodegen implements CodegenConfig {
r.isDouble = Boolean.TRUE;
}
} else if (ModelUtils.isTypeObjectSchema(responseSchema)) {
if (ModelUtils.isFreeFormObject(responseSchema)) {
if (ModelUtils.isFreeFormObject(responseSchema, openAPI)) {
r.isFreeFormObject = true;
} else {
r.isModel = true;
@@ -5189,7 +5189,7 @@ public class DefaultCodegen implements CodegenConfig {
}
ModelUtils.syncValidationProperties(parameterSchema, codegenParameter);
codegenParameter.setTypeProperties(parameterSchema);
codegenParameter.setTypeProperties(parameterSchema, openAPI);
codegenParameter.setComposedSchemas(getComposedSchemas(parameterSchema));
if (Boolean.TRUE.equals(parameterSchema.getNullable())) { // use nullable defined in the spec
@@ -5239,7 +5239,7 @@ public class DefaultCodegen implements CodegenConfig {
if (ModelUtils.isMapSchema(parameterSchema)) { // for map parameter
updateParameterForMap(codegenParameter, parameterSchema, imports);
}
if (ModelUtils.isFreeFormObject(parameterSchema)) {
if (ModelUtils.isFreeFormObject(parameterSchema, openAPI)) {
codegenParameter.isFreeFormObject = true;
}
addVarsRequiredVarsAdditionalProps(parameterSchema, codegenParameter);
@@ -7115,7 +7115,7 @@ public class DefaultCodegen implements CodegenConfig {
Schema ps = unaliasSchema(propertySchema);
ModelUtils.syncValidationProperties(ps, codegenParameter);
codegenParameter.setTypeProperties(ps);
codegenParameter.setTypeProperties(ps, openAPI);
codegenParameter.setComposedSchemas(getComposedSchemas(ps));
if (ps.getPattern() != null) {
codegenParameter.pattern = toRegularExpression(ps.getPattern());
@@ -7206,7 +7206,7 @@ public class DefaultCodegen implements CodegenConfig {
codegenParameter.isPrimitiveType = false;
codegenParameter.items = codegenProperty.items;
codegenParameter.mostInnerItems = codegenProperty.mostInnerItems;
} else if (ModelUtils.isFreeFormObject(ps)) {
} else if (ModelUtils.isFreeFormObject(ps, openAPI)) {
codegenParameter.isFreeFormObject = true;
}
} else if (ModelUtils.isNullType(ps)) {
@@ -7382,7 +7382,7 @@ public class DefaultCodegen implements CodegenConfig {
if (StringUtils.isBlank(name)) {
useModel = false;
} else {
if (ModelUtils.isFreeFormObject(schema)) {
if (ModelUtils.isFreeFormObject(schema, openAPI)) {
useModel = ModelUtils.shouldGenerateFreeFormObjectModel(name, this);
} else if (ModelUtils.isMapSchema(schema)) {
useModel = ModelUtils.shouldGenerateMapModel(schema);
@@ -7461,7 +7461,7 @@ public class DefaultCodegen implements CodegenConfig {
if (ModelUtils.isMapSchema(schema)) {
// Schema with additionalproperties: true (including composed schemas with additionalproperties: true)
updateRequestBodyForMap(codegenParameter, schema, name, imports, bodyParameterName);
} else if (ModelUtils.isFreeFormObject(schema)) {
} else if (ModelUtils.isFreeFormObject(schema, openAPI)) {
// non-composed object type with no properties + additionalProperties
// additionalProperties must be null, ObjectSchema, or empty Schema
codegenParameter.isFreeFormObject = true;
@@ -7724,7 +7724,7 @@ public class DefaultCodegen implements CodegenConfig {
schema = ModelUtils.getReferencedSchema(this.openAPI, schema);
ModelUtils.syncValidationProperties(unaliasedSchema, codegenParameter);
codegenParameter.setTypeProperties(unaliasedSchema);
codegenParameter.setTypeProperties(unaliasedSchema, openAPI);
codegenParameter.setComposedSchemas(getComposedSchemas(unaliasedSchema));
// TODO in the future switch al the below schema usages to unaliasedSchema
// because it keeps models as refs and will not get their referenced schemas

View File

@@ -492,7 +492,7 @@ public class DefaultGenerator implements Generator {
if (schema.getExtensions() != null && Boolean.TRUE.equals(schema.getExtensions().get("x-internal"))) {
LOGGER.info("Model {} not generated since x-internal is set to true", name);
continue;
} else if (ModelUtils.isFreeFormObject(schema)) { // check to see if it's a free-form object
} else if (ModelUtils.isFreeFormObject(schema, openAPI)) { // check to see if it's a free-form object
if (!ModelUtils.shouldGenerateFreeFormObjectModel(name, config)) {
LOGGER.info("Model {} not generated since it's a free-form object", name);
continue;

View File

@@ -13,6 +13,7 @@ import org.openapitools.codegen.meta.FeatureSet;
import org.openapitools.codegen.meta.features.SchemaSupportFeature;
import org.openapitools.codegen.utils.ModelUtils;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.media.Schema;
public interface IJsonSchemaValidationProperties {
@@ -283,7 +284,7 @@ public interface IJsonSchemaValidationProperties {
*
* @param p the schema which contains the type info
*/
default void setTypeProperties(Schema p) {
default void setTypeProperties(Schema p, OpenAPI openAPI) {
if (ModelUtils.isModelWithPropertiesOnly(p)) {
setIsModel(true);
} else if (ModelUtils.isArraySchema(p)) {
@@ -336,7 +337,7 @@ public interface IJsonSchemaValidationProperties {
setIsNull(true);
} else if (ModelUtils.isAnyType(p)) {
setIsAnyType(true);
} else if (ModelUtils.isFreeFormObject(p)) {
} else if (ModelUtils.isFreeFormObject(p, openAPI)) {
setIsFreeFormObject(true);
// TODO: remove below later after updating generators to properly use isFreeFormObject
setIsMap(true);

View File

@@ -1117,7 +1117,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
addAdditionPropertiesToCodeGenModel(m, schema);
} else {
m.setIsMap(false);
if (ModelUtils.isFreeFormObject(schema)) {
if (ModelUtils.isFreeFormObject(schema, openAPI)) {
// non-composed object type with no properties + additionalProperties
// additionalProperties must be null, ObjectSchema, or empty Schema
addAdditionPropertiesToCodeGenModel(m, schema);

View File

@@ -1702,7 +1702,7 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen {
addAdditionPropertiesToCodeGenModel(m, schema);
} else {
m.setIsMap(false);
if (ModelUtils.isFreeFormObject(schema)) {
if (ModelUtils.isFreeFormObject(schema, openAPI)) {
// non-composed object type with no properties + additionalProperties
// additionalProperties must be null, ObjectSchema, or empty Schema
addAdditionPropertiesToCodeGenModel(m, schema);

View File

@@ -1123,7 +1123,7 @@ public class CSharpReducedClientCodegen extends AbstractCSharpCodegen {
addAdditionPropertiesToCodeGenModel(m, schema);
} else {
m.setIsMap(false);
if (ModelUtils.isFreeFormObject(schema)) {
if (ModelUtils.isFreeFormObject(schema, openAPI)) {
// non-composed object type with no properties + additionalProperties
// additionalProperties must be null, ObjectSchema, or empty Schema
addAdditionPropertiesToCodeGenModel(m, schema);

View File

@@ -423,7 +423,7 @@ public class CppRestSdkClientCodegen extends AbstractCppCodegen {
return "new " + toModelName(ModelUtils.getSimpleRef(p.get$ref())) + "()";
} else if (ModelUtils.isStringSchema(p)) {
return "utility::conversions::to_string_t(\"\")";
} else if (ModelUtils.isFreeFormObject(p)) {
} else if (ModelUtils.isFreeFormObject(p, openAPI)) {
return "new Object()";
}

View File

@@ -134,7 +134,7 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
if (ModelUtils.isMapSchema(p)) {
String inner = getSchemaType(ModelUtils.getAdditionalProperties(p));
return "Map[String, " + inner + "]() ";
} else if (ModelUtils.isFreeFormObject(p)) {
} else if (ModelUtils.isFreeFormObject(p, openAPI)) {
// We're opinionated in this template to use ujson
return "ujson.Null";
}
@@ -143,7 +143,7 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
@Override
public String getSchemaType(Schema p) {
if (ModelUtils.isFreeFormObject(p)) {
if (ModelUtils.isFreeFormObject(p, openAPI)) {
// We're opinionated in this template to use ujson
return "Value";
}
@@ -829,7 +829,7 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
CodegenProperty property = super.fromProperty(name, schema);
// Customize type for freeform objects
if (ModelUtils.isFreeFormObject(schema)) {
if (ModelUtils.isFreeFormObject(schema, openAPI)) {
property.dataType = "Value";
property.baseType = "Value";
}
@@ -839,7 +839,7 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
@Override
public String getTypeDeclaration(Schema schema) {
if (ModelUtils.isFreeFormObject(schema)) {
if (ModelUtils.isFreeFormObject(schema, openAPI)) {
return "Value";
}
return super.getTypeDeclaration(schema);

View File

@@ -844,9 +844,10 @@ public class ModelUtils {
* The value can be any type except the 'null' value.
*
* @param schema potentially containing a '$ref'
* @param openAPI document containing the Schema.
* @return true if it's a free-form object
*/
public static boolean isFreeFormObject(Schema schema) {
public static boolean isFreeFormObject(Schema schema, OpenAPI openAPI) {
if (schema == null) {
// TODO: Is this message necessary? A null schema is not a free-form object, so the result is correct.
once(LOGGER).error("Schema cannot be null in isFreeFormObject check");
@@ -905,6 +906,8 @@ public class ModelUtils {
if (addlProps == null) {
return true;
} else {
addlProps = getReferencedSchema(openAPI, addlProps);
if (addlProps instanceof ObjectSchema) {
ObjectSchema objSchema = (ObjectSchema) addlProps;
// additionalProperties defined as {}

View File

@@ -142,7 +142,7 @@ public class ModelUtilsTest {
Schema commandSchema = ModelUtils.getSchema(openAPI, "Command");
Assert.assertTrue(ModelUtils.isModel(commandSchema));
Assert.assertFalse(ModelUtils.isFreeFormObject(commandSchema));
Assert.assertFalse(ModelUtils.isFreeFormObject(commandSchema, openAPI));
}
@Test
@@ -247,23 +247,23 @@ public class ModelUtilsTest {
OpenAPI openAPI = new OpenAPI().openapi("3.0.0");
// Create initial "empty" object schema.
ObjectSchema objSchema = new ObjectSchema();
Assert.assertTrue(ModelUtils.isFreeFormObject(objSchema));
Assert.assertTrue(ModelUtils.isFreeFormObject(objSchema, openAPI));
// Set additionalProperties to an empty ObjectSchema.
objSchema.setAdditionalProperties(new ObjectSchema());
Assert.assertTrue(ModelUtils.isFreeFormObject(objSchema));
Assert.assertTrue(ModelUtils.isFreeFormObject(objSchema, openAPI));
// Add a single property to the schema (no longer a free-form object).
Map<String, Schema> props = new HashMap<>();
props.put("prop1", new StringSchema());
objSchema.setProperties(props);
Assert.assertFalse(ModelUtils.isFreeFormObject(objSchema));
Assert.assertFalse(ModelUtils.isFreeFormObject(objSchema, openAPI));
// Test a non-object schema
Assert.assertFalse(ModelUtils.isFreeFormObject(new StringSchema()));
Assert.assertFalse(ModelUtils.isFreeFormObject(new StringSchema(), openAPI));
// Test a null schema
Assert.assertFalse(ModelUtils.isFreeFormObject(null));
Assert.assertFalse(ModelUtils.isFreeFormObject(null, openAPI));
}
@Test
@@ -326,9 +326,9 @@ public class ModelUtilsTest {
Assert.assertTrue(ModelUtils.isMapSchema((Schema) misc.getProperties().get("map1")));
// test free form object
Assert.assertTrue(ModelUtils.isFreeFormObject((Schema) misc.getProperties().get("free_form_object_1")));
Assert.assertTrue(ModelUtils.isFreeFormObject((Schema) misc.getProperties().get("free_form_object_2")));
Assert.assertTrue(ModelUtils.isFreeFormObject((Schema) misc.getProperties().get("free_form_object_3")));
Assert.assertTrue(ModelUtils.isFreeFormObject((Schema) misc.getProperties().get("free_form_object_1"), openAPI));
Assert.assertTrue(ModelUtils.isFreeFormObject((Schema) misc.getProperties().get("free_form_object_2"), openAPI));
Assert.assertTrue(ModelUtils.isFreeFormObject((Schema) misc.getProperties().get("free_form_object_3"), openAPI));
// test oneOf
Assert.assertTrue(ModelUtils.isOneOf((Schema) misc.getProperties().get("oneof1")));
@@ -360,9 +360,9 @@ public class ModelUtilsTest {
Assert.assertTrue(ModelUtils.isMapSchema((Schema) misc.getProperties().get("map1")));
// test free form object
Assert.assertTrue(ModelUtils.isFreeFormObject((Schema) misc.getProperties().get("free_form_object_1")));
Assert.assertTrue(ModelUtils.isFreeFormObject((Schema) misc.getProperties().get("free_form_object_2")));
Assert.assertTrue(ModelUtils.isFreeFormObject((Schema) misc.getProperties().get("free_form_object_3")));
Assert.assertTrue(ModelUtils.isFreeFormObject((Schema) misc.getProperties().get("free_form_object_1"), openAPI));
Assert.assertTrue(ModelUtils.isFreeFormObject((Schema) misc.getProperties().get("free_form_object_2"), openAPI));
Assert.assertTrue(ModelUtils.isFreeFormObject((Schema) misc.getProperties().get("free_form_object_3"), openAPI));
// test oneOf property
Assert.assertTrue(ModelUtils.isOneOf((Schema) misc.getProperties().get("oneof1")));

View File

@@ -526,6 +526,11 @@ components:
$ref: '#/components/schemas/12345AnyOfObject'
required:
- requiredAnyOf
AdditionalPropertiesReferencedAnyOfObject:
description: Check that an object with only additional properties that references another object (e.g. an anyOf object) isn't treated as freeForm
type: object
additionalProperties:
$ref: '#/components/schemas/AnyOfProperty'
AnyOfObject:
description: Test a model containing an anyOf
anyOf:

View File

@@ -4,6 +4,7 @@ Cargo.toml
README.md
api/openapi.yaml
bin/cli.rs
docs/AdditionalPropertiesReferencedAnyOfObject.md
docs/AdditionalPropertiesWithList.md
docs/AdditionalPropertiesWithNullable.md
docs/AnotherXmlArray.md

View File

@@ -182,6 +182,7 @@ Method | HTTP request | Description
## Documentation For Models
- [AdditionalPropertiesReferencedAnyOfObject](docs/AdditionalPropertiesReferencedAnyOfObject.md)
- [AdditionalPropertiesWithList](docs/AdditionalPropertiesWithList.md)
- [AdditionalPropertiesWithNullable](docs/AdditionalPropertiesWithNullable.md)
- [AnotherXmlArray](docs/AnotherXmlArray.md)

View File

@@ -536,6 +536,12 @@ components:
$ref: '#/components/schemas/12345AnyOfObject'
required:
- requiredAnyOf
AdditionalPropertiesReferencedAnyOfObject:
additionalProperties:
$ref: '#/components/schemas/AnyOfProperty'
description: Check that an object with only additional properties that references
another object (e.g. an anyOf object) isn't treated as freeForm
type: object
AnyOfObject:
anyOf:
- $ref: '#/components/schemas/AnyOfObject_anyOf'

View File

@@ -0,0 +1,9 @@
# AdditionalPropertiesReferencedAnyOfObject
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -6,6 +6,150 @@ use crate::models;
#[cfg(any(feature = "client", feature = "server"))]
use crate::header;
/// Check that an object with only additional properties that references another object (e.g. an anyOf object) isn't treated as freeForm
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
pub struct AdditionalPropertiesReferencedAnyOfObject(std::collections::HashMap<String, models::AnyOfProperty>);
impl std::convert::From<std::collections::HashMap<String, models::AnyOfProperty>> for AdditionalPropertiesReferencedAnyOfObject {
fn from(x: std::collections::HashMap<String, models::AnyOfProperty>) -> Self {
AdditionalPropertiesReferencedAnyOfObject(x)
}
}
impl std::convert::From<AdditionalPropertiesReferencedAnyOfObject> for std::collections::HashMap<String, models::AnyOfProperty> {
fn from(x: AdditionalPropertiesReferencedAnyOfObject) -> Self {
x.0
}
}
impl std::ops::Deref for AdditionalPropertiesReferencedAnyOfObject {
type Target = std::collections::HashMap<String, models::AnyOfProperty>;
fn deref(&self) -> &std::collections::HashMap<String, models::AnyOfProperty> {
&self.0
}
}
impl std::ops::DerefMut for AdditionalPropertiesReferencedAnyOfObject {
fn deref_mut(&mut self) -> &mut std::collections::HashMap<String, models::AnyOfProperty> {
&mut self.0
}
}
/// Converts the AdditionalPropertiesReferencedAnyOfObject value to the Query Parameters representation (style=form, explode=false)
/// specified in https://swagger.io/docs/specification/serialization/
/// Should be implemented in a serde serializer
impl ::std::string::ToString for AdditionalPropertiesReferencedAnyOfObject {
fn to_string(&self) -> String {
// ToString for this model is not supported
"".to_string()
}
}
/// Converts Query Parameters representation (style=form, explode=false) to a AdditionalPropertiesReferencedAnyOfObject value
/// as specified in https://swagger.io/docs/specification/serialization/
/// Should be implemented in a serde deserializer
impl ::std::str::FromStr for AdditionalPropertiesReferencedAnyOfObject {
type Err = &'static str;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
std::result::Result::Err("Parsing AdditionalPropertiesReferencedAnyOfObject is not supported")
}
}
// Methods for converting between header::IntoHeaderValue<AdditionalPropertiesReferencedAnyOfObject> and hyper::header::HeaderValue
#[cfg(any(feature = "client", feature = "server"))]
impl std::convert::TryFrom<header::IntoHeaderValue<AdditionalPropertiesReferencedAnyOfObject>> for hyper::header::HeaderValue {
type Error = String;
fn try_from(hdr_value: header::IntoHeaderValue<AdditionalPropertiesReferencedAnyOfObject>) -> std::result::Result<Self, Self::Error> {
let hdr_value = hdr_value.to_string();
match hyper::header::HeaderValue::from_str(&hdr_value) {
std::result::Result::Ok(value) => std::result::Result::Ok(value),
std::result::Result::Err(e) => std::result::Result::Err(
format!("Invalid header value for AdditionalPropertiesReferencedAnyOfObject - value: {} is invalid {}",
hdr_value, e))
}
}
}
#[cfg(any(feature = "client", feature = "server"))]
impl std::convert::TryFrom<hyper::header::HeaderValue> for header::IntoHeaderValue<AdditionalPropertiesReferencedAnyOfObject> {
type Error = String;
fn try_from(hdr_value: hyper::header::HeaderValue) -> std::result::Result<Self, Self::Error> {
match hdr_value.to_str() {
std::result::Result::Ok(value) => {
match <AdditionalPropertiesReferencedAnyOfObject as std::str::FromStr>::from_str(value) {
std::result::Result::Ok(value) => std::result::Result::Ok(header::IntoHeaderValue(value)),
std::result::Result::Err(err) => std::result::Result::Err(
format!("Unable to convert header value '{}' into AdditionalPropertiesReferencedAnyOfObject - {}",
value, err))
}
},
std::result::Result::Err(e) => std::result::Result::Err(
format!("Unable to convert header: {:?} to string: {}",
hdr_value, e))
}
}
}
#[cfg(feature = "server")]
impl std::convert::TryFrom<header::IntoHeaderValue<Vec<AdditionalPropertiesReferencedAnyOfObject>>> for hyper::header::HeaderValue {
type Error = String;
fn try_from(hdr_values: header::IntoHeaderValue<Vec<AdditionalPropertiesReferencedAnyOfObject>>) -> std::result::Result<Self, Self::Error> {
let hdr_values : Vec<String> = hdr_values.0.into_iter().map(|hdr_value| {
hdr_value.to_string()
}).collect();
match hyper::header::HeaderValue::from_str(&hdr_values.join(", ")) {
std::result::Result::Ok(hdr_value) => std::result::Result::Ok(hdr_value),
std::result::Result::Err(e) => std::result::Result::Err(format!("Unable to convert {:?} into a header - {}",
hdr_values, e))
}
}
}
#[cfg(feature = "server")]
impl std::convert::TryFrom<hyper::header::HeaderValue> for header::IntoHeaderValue<Vec<AdditionalPropertiesReferencedAnyOfObject>> {
type Error = String;
fn try_from(hdr_values: hyper::header::HeaderValue) -> std::result::Result<Self, Self::Error> {
match hdr_values.to_str() {
std::result::Result::Ok(hdr_values) => {
let hdr_values : std::vec::Vec<AdditionalPropertiesReferencedAnyOfObject> = hdr_values
.split(',')
.filter_map(|hdr_value| match hdr_value.trim() {
"" => std::option::Option::None,
hdr_value => std::option::Option::Some({
match <AdditionalPropertiesReferencedAnyOfObject as std::str::FromStr>::from_str(hdr_value) {
std::result::Result::Ok(value) => std::result::Result::Ok(value),
std::result::Result::Err(err) => std::result::Result::Err(
format!("Unable to convert header value '{}' into AdditionalPropertiesReferencedAnyOfObject - {}",
hdr_value, err))
}
})
}).collect::<std::result::Result<std::vec::Vec<_>, String>>()?;
std::result::Result::Ok(header::IntoHeaderValue(hdr_values))
},
std::result::Result::Err(e) => std::result::Result::Err(format!("Unable to parse header: {:?} as a string - {}",
hdr_values, e)),
}
}
}
impl AdditionalPropertiesReferencedAnyOfObject {
/// Helper function to allow us to convert this model to an XML string.
/// Will panic if serialisation fails.
#[allow(dead_code)]
pub(crate) fn as_xml(&self) -> String {
serde_xml_rs::to_string(&self).expect("impossible to fail to serialize")
}
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
pub struct AdditionalPropertiesWithList(std::collections::HashMap<String, Vec<String>>);