diff --git a/codegenerator/model.py b/codegenerator/model.py index 77e38e4..10a8b1a 100644 --- a/codegenerator/model.py +++ b/codegenerator/model.py @@ -380,6 +380,10 @@ class JsonSchemaParser: field = StructField(data_type=data_type) field.description = v.get("description") + if not field.description and isinstance( + data_type, PrimitiveAny + ): + field.description = "OpenAPI specifies the field as '{}'." if k in required: field.is_required = True if min_ver: diff --git a/codegenerator/rust_cli.py b/codegenerator/rust_cli.py index d4c47c0..b6a4751 100644 --- a/codegenerator/rust_cli.py +++ b/codegenerator/rust_cli.py @@ -11,17 +11,18 @@ # under the License. # import logging -from pathlib import Path -import subprocess import re +import subprocess +from pathlib import Path +from codegenerator import common, model from codegenerator.base import BaseGenerator -from codegenerator import common -from codegenerator import model +from codegenerator.common import ( + BaseCombinedType, + BaseCompoundType, + BasePrimitiveType, +) from codegenerator.common import rust as common_rust -from codegenerator.common import BasePrimitiveType -from codegenerator.common import BaseCombinedType -from codegenerator.common import BaseCompoundType BASIC_FIELDS = [ "id", @@ -86,6 +87,17 @@ class JsonValue(common_rust.JsonValue): return imports +class JsonValueDefaultNull(JsonValue): + """Arbitrary JSON value""" + + clap_macros: set[str] = { + 'value_name="JSON"', + "value_parser=crate::common::parse_json", + "default_value_t=Value::Null", + } + original_data_type: BaseCombinedType | BaseCompoundType | None = None + + class StructInputField(common_rust.StructField): """Structure field of the CLI input""" @@ -592,6 +604,16 @@ class RequestTypeManager(common_rust.TypeManager): simplified_data_type.original_data_type = field_data_type field_data_type = simplified_data_type self.ignored_models.append(field.data_type) + if ( + field.is_required + and isinstance(field.data_type, model.PrimitiveAny) + and len(type_model.fields) == 1 + ): + # When a only field of the struct is mandatory and is defined as + # '{}' most likely it is expecting the Null. We cannot trust + # this 100% but we can define the default value as Value::Null + # while still giving the user possibility to pass a real value. + field_data_type = JsonValueDefaultNull() f = field_class( local_name=self.get_local_attribute_name(field_name), remote_name=self.get_remote_attribute_name(field_name), diff --git a/codegenerator/templates/rust_macros.j2 b/codegenerator/templates/rust_macros.j2 index 1a1472e..e8d433d 100644 --- a/codegenerator/templates/rust_macros.j2 +++ b/codegenerator/templates/rust_macros.j2 @@ -199,7 +199,8 @@ Some({{ val }}) {%- elif param.data_type.__class__.__name__ in ["ArrayInput"] %} {{ sdk_plain_array_setter(param, val_var.replace("&", ""), dst_var, by_ref=by_ref) }} -{%- elif param.data_type.__class__.__name__ in ["JsonValue"] %} +{%- elif param.data_type.__class__.__name__ in ["JsonValue", +"JsonValueDefaultNull"] %} {%- set original_type = param.data_type.original_data_type %} {%- if original_type and original_type.__class__.__name__ == "StructInput" %} @@ -300,7 +301,7 @@ Some({{ val }}) {{ dst_var }}.{{ param.remote_name }}({{ builder_name }}.build().wrap_err("error preparing the request data")?); } - {%- elif param.data_type.item_type.__class__.__name__ == "JsonValue" %} + {%- elif param.data_type.item_type.__class__.__name__ in ["JsonValue", "JsonValueDefaultNull"] %} {#- atm it is not possible to pass ownership of Option #} if let Some(val) = {{ val_var }} { {{ dst_var }}.{{ param.remote_name }}(val.clone());