From 0e42724990d415230ad64924ff09d5c7e2b1a896 Mon Sep 17 00:00:00 2001 From: Enrique Fernandez Date: Sun, 27 Apr 2025 16:32:28 +0200 Subject: [PATCH 1/9] feat: use typed ecto schemas in generated models --- .../languages/ElixirClientCodegen.java | 179 ++++++++++++++++-- .../resources/elixir/deserializer.ex.mustache | 114 ----------- .../src/main/resources/elixir/model.mustache | 40 ++-- .../elixir/request_builder.ex.mustache | 20 +- .../petstore/elixir/.openapi-generator/FILES | 1 - .../lib/openapi_petstore/deserializer.ex | 116 ------------ .../model/_foo_get_default_response.ex | 21 +- .../model/_special_model_name_.ex | 19 +- .../model/additional_properties_class.ex | 21 +- .../model/all_of_with_single_ref.ex | 23 ++- .../lib/openapi_petstore/model/animal.ex | 21 +- .../elixir/lib/openapi_petstore/model/any.ex | 19 +- .../openapi_petstore/model/api_response.ex | 23 ++- .../model/array_of_array_of_number_only.ex | 19 +- .../model/array_of_number_only.ex | 19 +- .../lib/openapi_petstore/model/array_test.ex | 23 ++- .../openapi_petstore/model/capitalization.ex | 29 +-- .../elixir/lib/openapi_petstore/model/cat.ex | 23 ++- .../lib/openapi_petstore/model/category.ex | 21 +- .../model/child_with_nullable.ex | 23 ++- .../lib/openapi_petstore/model/class_model.ex | 19 +- .../lib/openapi_petstore/model/client.ex | 19 +- .../model/deprecated_model.ex | 19 +- .../elixir/lib/openapi_petstore/model/dog.ex | 23 ++- .../lib/openapi_petstore/model/enum_arrays.ex | 21 +- .../lib/openapi_petstore/model/enum_class.ex | 18 +- .../lib/openapi_petstore/model/enum_test.ex | 41 ++-- .../fake_big_decimal_map_200_response.ex | 21 +- .../elixir/lib/openapi_petstore/model/file.ex | 19 +- .../model/file_schema_test_class.ex | 25 +-- .../elixir/lib/openapi_petstore/model/foo.ex | 19 +- .../lib/openapi_petstore/model/format_test.ex | 49 ++--- .../model/has_only_read_only.ex | 21 +- .../model/health_check_result.ex | 19 +- .../elixir/lib/openapi_petstore/model/list.ex | 19 +- .../lib/openapi_petstore/model/map_test.ex | 25 ++- ...perties_and_additional_properties_class.ex | 24 +-- .../model/model_200_response.ex | 21 +- .../elixir/lib/openapi_petstore/model/name.ex | 25 ++- .../openapi_petstore/model/nullable_class.ex | 41 ++-- .../lib/openapi_petstore/model/number_only.ex | 19 +- .../model/object_with_deprecated_fields.ex | 27 +-- .../lib/openapi_petstore/model/order.ex | 29 +-- .../openapi_petstore/model/outer_composite.ex | 23 ++- .../lib/openapi_petstore/model/outer_enum.ex | 18 +- .../model/outer_enum_default_value.ex | 18 +- .../model/outer_enum_integer.ex | 18 +- .../model/outer_enum_integer_default_value.ex | 18 +- .../model/outer_object_with_enum_property.ex | 21 +- .../model/parent_with_nullable.ex | 21 +- .../elixir/lib/openapi_petstore/model/pet.ex | 34 ++-- .../openapi_petstore/model/read_only_first.ex | 21 +- .../lib/openapi_petstore/model/return.ex | 19 +- .../openapi_petstore/model/single_ref_type.ex | 18 +- .../elixir/lib/openapi_petstore/model/tag.ex | 21 +- ..._freeform_additional_properties_request.ex | 19 +- .../elixir/lib/openapi_petstore/model/user.ex | 33 ++-- .../lib/openapi_petstore/request_builder.ex | 20 +- samples/client/petstore/elixir/mix.exs | 1 + .../petstore/elixir/test/outer_enum_test.exs | 21 +- 60 files changed, 937 insertions(+), 744 deletions(-) delete mode 100644 modules/openapi-generator/src/main/resources/elixir/deserializer.ex.mustache delete mode 100644 samples/client/petstore/elixir/lib/openapi_petstore/deserializer.ex diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java index 5af1d9238904..9b3072e2c540 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java @@ -60,6 +60,7 @@ public class ElixirClientCodegen extends DefaultCodegen { String supportedElixirVersion = "1.18"; List extraApplications = Arrays.asList(":logger"); List deps = Arrays.asList( + "{:ecto, \"~> 3.12\"}", "{:tesla, \"~> 1.14\"}", "{:ex_doc, \"~> 0.37.3\", only: :dev, runtime: false}", "{:dialyxir, \"~> 1.4\", only: [:dev, :test], runtime: false}"); @@ -336,10 +337,6 @@ public void preprocessOpenAPI(OpenAPI openAPI) { supportingFiles.add(new SupportingFile("request_builder.ex.mustache", sourceFolder(), "request_builder.ex")); - - supportingFiles.add(new SupportingFile("deserializer.ex.mustache", - sourceFolder(), - "deserializer.ex")); } @Override @@ -384,7 +381,52 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List vars = new ArrayList<>(ecm.vars); + ecm.vars.clear(); + for (CodegenProperty var : vars) { + ecm.vars.add(new ExtendedCodegenProperty(var)); + } + + List allVars = new ArrayList<>(ecm.allVars); + ecm.allVars.clear(); + for (CodegenProperty var : allVars) { + ecm.allVars.add(new ExtendedCodegenProperty(var)); + } + + List requiredVars = new ArrayList<>(ecm.requiredVars); + ecm.requiredVars.clear(); + for (CodegenProperty var : requiredVars) { + ecm.requiredVars.add(new ExtendedCodegenProperty(var)); + } + + List optionalVars = new ArrayList<>(ecm.optionalVars); + ecm.optionalVars.clear(); + for (CodegenProperty var : optionalVars) { + ecm.optionalVars.add(new ExtendedCodegenProperty(var)); + } + + List ectoFields = new ArrayList<>(ecm.ectoFields); + ecm.ectoFields.clear(); + for (CodegenProperty field : ectoFields) { + ecm.ectoFields.add(new ExtendedCodegenProperty(field)); + } + + List ectoEmbeds = new ArrayList<>(ecm.ectoEmbeds); + ecm.ectoEmbeds.clear(); + for (CodegenProperty embed : ectoEmbeds) { + ecm.ectoEmbeds.add(new ExtendedCodegenProperty(embed)); + } + + List requiredEctoFields = new ArrayList<>(ecm.requiredEctoFields); + ecm.requiredEctoFields.clear(); + for (CodegenProperty field : requiredEctoFields) { + ecm.requiredEctoFields.add(new ExtendedCodegenProperty(field)); + } + + return ecm; } @Override @@ -865,6 +907,9 @@ private boolean getRequiresHttpcWorkaround() { class ExtendedCodegenModel extends CodegenModel { public boolean hasImports; + public List ectoFields = new ArrayList<>(); + public List ectoEmbeds = new ArrayList<>(); + public List requiredEctoFields = new ArrayList<>(); public ExtendedCodegenModel(CodegenModel cm) { super(); @@ -918,15 +963,127 @@ public ExtendedCodegenModel(CodegenModel cm) { this.additionalPropertiesType = cm.additionalPropertiesType; this.hasImports = !this.imports.isEmpty(); - } - public boolean hasComplexVars() { - for (CodegenProperty p : vars) { - if (!p.isPrimitiveType) { - return true; + for (CodegenProperty var : this.vars) { + if (var.isPrimitiveType || var.isMap) { + this.ectoFields.add(var); + if (var.required) { + this.requiredEctoFields.add(var); + } + } else { + this.ectoEmbeds.add(var); } } - return false; + } + } + + class ExtendedCodegenProperty extends CodegenProperty { + public ExtendedCodegenProperty(CodegenProperty cp) { + super(); + + // Copy all fields of CodegenProperty + this.openApiType = cp.openApiType; + this.baseName = cp.baseName; + this.complexType = cp.complexType; + this.getter = cp.getter; + this.setter = cp.setter; + this.description = cp.description; + this.dataType = cp.dataType; + this.datatypeWithEnum = cp.datatypeWithEnum; + this.dataFormat = cp.dataFormat; + this.name = cp.name; + this.min = cp.min; + this.max = cp.max; + this.defaultValue = cp.defaultValue; + this.defaultValueWithParam = cp.defaultValueWithParam; + this.baseType = cp.baseType; + this.containerType = cp.containerType; + this.title = cp.title; + this.unescapedDescription = cp.unescapedDescription; + this.maxLength = cp.maxLength; + this.minLength = cp.minLength; + this.pattern = cp.pattern; + this.example = cp.example; + this.jsonSchema = cp.jsonSchema; + this.minimum = cp.minimum; + this.maximum = cp.maximum; + this.exclusiveMinimum = cp.exclusiveMinimum; + this.exclusiveMaximum = cp.exclusiveMaximum; + this.required = cp.required; + this.deprecated = cp.deprecated; + this.isPrimitiveType = cp.isPrimitiveType; + this.isModel = cp.isModel; + this.isContainer = cp.isContainer; + this.isString = cp.isString; + this.isNumeric = cp.isNumeric; + this.isInteger = cp.isInteger; + this.isLong = cp.isLong; + this.isNumber = cp.isNumber; + this.isFloat = cp.isFloat; + this.isDouble = cp.isDouble; + this.isByteArray = cp.isByteArray; + this.isBinary = cp.isBinary; + this.isFile = cp.isFile; + this.isBoolean = cp.isBoolean; + this.isDate = cp.isDate; + this.isDateTime = cp.isDateTime; + this.isUuid = cp.isUuid; + this.isEmail = cp.isEmail; + this.isModel = cp.isModel; + this.isNull = cp.isNull; + this.isArray = cp.isArray; + this.isMap = cp.isMap; + this.isEnum = cp.isEnum; + this.isReadOnly = cp.isReadOnly; + this.isWriteOnly = cp.isWriteOnly; + this.isNullable = cp.isNullable; + this._enum = cp._enum; + this.allowableValues = cp.allowableValues; + this.items = cp.items; + this.additionalProperties = cp.additionalProperties; + this.vars = cp.vars; + this.requiredVars = cp.requiredVars; + this.vendorExtensions = cp.vendorExtensions; + } + + public String ectoType() { + String ectoType = ectoType(this); + + if (":any".equals(ectoType)) { + return ectoType + ", virtual: true"; + } + + return ectoType; + } + + private String ectoType(CodegenProperty property) { + String baseType = property.baseType; + switch (baseType) { + case "integer()": + return ":integer"; + case "float()": + return ":float"; + case "number()": + return ":float"; + case "boolean()": + return ":boolean"; + case "String.t": + return ":string"; + case "Date.t": + return ":date"; + case "DateTime.t": + return ":utc_datetime"; + case "binary()": + return ":binary"; + case "list()": + return "{:array, " + ectoType(property.items) + "}"; + case "map()": + return ":map"; + case "nil": + return ":any"; + default: + return ":any"; + } } } diff --git a/modules/openapi-generator/src/main/resources/elixir/deserializer.ex.mustache b/modules/openapi-generator/src/main/resources/elixir/deserializer.ex.mustache deleted file mode 100644 index b0b0ad169119..000000000000 --- a/modules/openapi-generator/src/main/resources/elixir/deserializer.ex.mustache +++ /dev/null @@ -1,114 +0,0 @@ -{{>licenseInfo}} -defmodule {{moduleName}}.Deserializer do - @moduledoc """ - Helper functions for deserializing responses into models - """ - - def json_decode(json) do - JSON.decode(json) - end - - def json_decode(json, module) do - json - |> json_decode() - |> case do - {:ok, decoded} -> {:ok, to_struct(decoded, module)} - {:error, _} = error -> error - end - end - - @doc """ - Update the provided model with a deserialization of a nested value - """ - @spec deserialize(struct(), atom(), :date | :datetime | :list | :map | :struct, module()) :: - struct() - def deserialize(model, field, :list, module) do - model - |> Map.update!(field, fn - nil -> - nil - - list -> - Enum.map(list, &to_struct(&1, module)) - end) - end - - def deserialize(model, field, :struct, module) do - model - |> Map.update!(field, fn - nil -> - nil - - value -> - to_struct(value, module) - end) - end - - def deserialize(model, field, :map, module) do - maybe_transform_map = fn - nil -> - nil - - existing_value -> - Map.new(existing_value, fn - {key, value} -> - {key, to_struct(value, module)} - end) - end - - Map.update!(model, field, maybe_transform_map) - end - - def deserialize(model, field, :date, _) do - value = Map.get(model, field) - - case is_binary(value) do - true -> - case Date.from_iso8601(value) do - {:ok, date} -> Map.put(model, field, date) - _ -> model - end - - false -> - model - end - end - - def deserialize(model, field, :datetime, _) do - value = Map.get(model, field) - - case is_binary(value) do - true -> - case DateTime.from_iso8601(value) do - {:ok, datetime, _offset} -> Map.put(model, field, datetime) - _ -> model - end - - false -> - model - end - end - - defp to_struct(value, module) - defp to_struct(nil, _), do: nil - - defp to_struct(list, module) when is_list(list) and is_atom(module) do - Enum.map(list, &to_struct(&1, module)) - end - - defp to_struct(map, module) when is_map(map) and is_atom(module) do - model = struct(module) - - model - |> Map.keys() - |> List.delete(:__struct__) - |> Enum.reduce(model, fn field, acc -> - Map.replace(acc, field, Map.get(map, Atom.to_string(field))) - end) - |> module.decode() - end - - defp to_struct(value, module) when is_atom(module) do - module.decode(value) - end -end diff --git a/modules/openapi-generator/src/main/resources/elixir/model.mustache b/modules/openapi-generator/src/main/resources/elixir/model.mustache index e7afe8407d01..ca27997ebc14 100644 --- a/modules/openapi-generator/src/main/resources/elixir/model.mustache +++ b/modules/openapi-generator/src/main/resources/elixir/model.mustache @@ -3,34 +3,32 @@ @moduledoc """ {{&description}} """ - - @derive JSON.Encoder - defstruct [ - {{#vars}}{{#atom}}{{&baseName}}{{/atom}}{{^-last}}, - {{/-last}}{{/vars}} - ] + use Ecto.Schema @type t :: %__MODULE__{ {{#vars}}{{#atom}}{{&baseName}}{{/atom}} => {{{datatype}}}{{#isNullable}} | nil{{/isNullable}}{{^isNullable}}{{^required}} | nil{{/required}}{{/isNullable}}{{^-last}}, {{/-last}}{{/vars}} } -{{#hasComplexVars}} - alias {{&moduleName}}.Deserializer + @derive {JSON.Encoder, only: [{{#vars}}{{#atom}}{{&baseName}}{{/atom}}{{^-last}}, {{/-last}}{{/vars}}]} + @primary_key false + embedded_schema do + {{#ectoFields}} + field {{#atom}}{{&baseName}}{{/atom}}, {{{ectoType}}} + {{/ectoFields}} + {{#ectoEmbeds}} + {{^isArray}}embeds_one{{/isArray}}{{#isArray}}embeds_many{{/isArray}} {{#atom}}{{&baseName}}{{/atom}}, {{&moduleName}}.Model.{{^isArray}}{{{baseType}}}{{/isArray}}{{#isArray}}{{{items.baseType}}}{{/isArray}} + {{/ectoEmbeds}} + end - def decode(value) do - value - {{#vars}} - {{^isPrimitiveType}} - {{#baseType}} |> Deserializer.deserialize({{#atom}}{{&baseName}}{{/atom}}, {{#isArray}}:list, {{&moduleName}}.Model.{{{items.baseType}}}{{/isArray}}{{#isMap}}:map, {{&moduleName}}.Model.{{{items.baseType}}}{{/isMap}}{{#isDate}}:date, nil{{/isDate}}{{#isDateTime}}:datetime, nil{{/isDateTime}}{{^isDate}}{{^isDateTime}}{{^isMap}}{{^isArray}}:struct, {{moduleName}}.Model.{{baseType}}{{/isArray}}{{/isMap}}{{/isDateTime}}{{/isDate}}) - {{/baseType}} - {{/isPrimitiveType}} - {{/vars}} -{{/hasComplexVars}} -{{^hasComplexVars}} - def decode(value) do - value -{{/hasComplexVars}} + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [{{#ectoFields}}{{#atom}}{{&baseName}}{{/atom}}{{^-last}}, {{/-last}}{{/ectoFields}}]) + |> Ecto.Changeset.validate_required([{{#requiredEctoFields}}{{#atom}}{{&baseName}}{{/atom}}{{^-last}}, {{/-last}}{{/requiredEctoFields}}]) + {{#ectoEmbeds}} + |> Ecto.Changeset.cast_embed({{#atom}}{{&baseName}}{{/atom}}{{#required}}, required: true{{/required}}) + {{/ectoEmbeds}} end end {{/model}}{{/models}} diff --git a/modules/openapi-generator/src/main/resources/elixir/request_builder.ex.mustache b/modules/openapi-generator/src/main/resources/elixir/request_builder.ex.mustache index 05a8527bdca7..e89e548a67df 100644 --- a/modules/openapi-generator/src/main/resources/elixir/request_builder.ex.mustache +++ b/modules/openapi-generator/src/main/resources/elixir/request_builder.ex.mustache @@ -187,10 +187,26 @@ defmodule {{moduleName}}.RequestBuilder do defp decode(%Tesla.Env{} = env, false), do: {:ok, env} defp decode(%Tesla.Env{body: body}, %{}) do - {{moduleName}}.Deserializer.json_decode(body) + JSON.decode(body) end defp decode(%Tesla.Env{body: body}, module) do - {{moduleName}}.Deserializer.json_decode(body, module) + case JSON.decode(body) do + {:ok, objects} when is_list(objects) -> + models = Enum.map(objects, fn object -> + {:ok, model} = to_model(module, object) + model + end) + {:ok, models} + {:ok, params} -> to_model(module, params) + {:error, error} -> {:error, error} + end + end + + defp to_model(module, params) do + module + |> struct + |> module.changeset(params) + |> Ecto.Changeset.apply_action(:insert) end end diff --git a/samples/client/petstore/elixir/.openapi-generator/FILES b/samples/client/petstore/elixir/.openapi-generator/FILES index baf3f42cbc21..7aeefea2dfb2 100644 --- a/samples/client/petstore/elixir/.openapi-generator/FILES +++ b/samples/client/petstore/elixir/.openapi-generator/FILES @@ -11,7 +11,6 @@ lib/openapi_petstore/api/pet.ex lib/openapi_petstore/api/store.ex lib/openapi_petstore/api/user.ex lib/openapi_petstore/connection.ex -lib/openapi_petstore/deserializer.ex lib/openapi_petstore/model/_foo_get_default_response.ex lib/openapi_petstore/model/_special_model_name_.ex lib/openapi_petstore/model/additional_properties_class.ex diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/deserializer.ex b/samples/client/petstore/elixir/lib/openapi_petstore/deserializer.ex deleted file mode 100644 index 62eb1c366c16..000000000000 --- a/samples/client/petstore/elixir/lib/openapi_petstore/deserializer.ex +++ /dev/null @@ -1,116 +0,0 @@ -# NOTE: This file is auto generated by OpenAPI Generator 7.14.0-SNAPSHOT (https://openapi-generator.tech). -# Do not edit this file manually. - -defmodule OpenapiPetstore.Deserializer do - @moduledoc """ - Helper functions for deserializing responses into models - """ - - def json_decode(json) do - JSON.decode(json) - end - - def json_decode(json, module) do - json - |> json_decode() - |> case do - {:ok, decoded} -> {:ok, to_struct(decoded, module)} - {:error, _} = error -> error - end - end - - @doc """ - Update the provided model with a deserialization of a nested value - """ - @spec deserialize(struct(), atom(), :date | :datetime | :list | :map | :struct, module()) :: - struct() - def deserialize(model, field, :list, module) do - model - |> Map.update!(field, fn - nil -> - nil - - list -> - Enum.map(list, &to_struct(&1, module)) - end) - end - - def deserialize(model, field, :struct, module) do - model - |> Map.update!(field, fn - nil -> - nil - - value -> - to_struct(value, module) - end) - end - - def deserialize(model, field, :map, module) do - maybe_transform_map = fn - nil -> - nil - - existing_value -> - Map.new(existing_value, fn - {key, value} -> - {key, to_struct(value, module)} - end) - end - - Map.update!(model, field, maybe_transform_map) - end - - def deserialize(model, field, :date, _) do - value = Map.get(model, field) - - case is_binary(value) do - true -> - case Date.from_iso8601(value) do - {:ok, date} -> Map.put(model, field, date) - _ -> model - end - - false -> - model - end - end - - def deserialize(model, field, :datetime, _) do - value = Map.get(model, field) - - case is_binary(value) do - true -> - case DateTime.from_iso8601(value) do - {:ok, datetime, _offset} -> Map.put(model, field, datetime) - _ -> model - end - - false -> - model - end - end - - defp to_struct(value, module) - defp to_struct(nil, _), do: nil - - defp to_struct(list, module) when is_list(list) and is_atom(module) do - Enum.map(list, &to_struct(&1, module)) - end - - defp to_struct(map, module) when is_map(map) and is_atom(module) do - model = struct(module) - - model - |> Map.keys() - |> List.delete(:__struct__) - |> Enum.reduce(model, fn field, acc -> - Map.replace(acc, field, Map.get(map, Atom.to_string(field))) - end) - |> module.decode() - end - - defp to_struct(value, module) when is_atom(module) do - module.decode(value) - end -end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/_foo_get_default_response.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/_foo_get_default_response.ex index b272dadafc26..68c60d6b2140 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/_foo_get_default_response.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/_foo_get_default_response.ex @@ -5,21 +5,24 @@ defmodule OpenapiPetstore.Model.FooGetDefaultResponse do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :string - ] + use Ecto.Schema @type t :: %__MODULE__{ :string => OpenapiPetstore.Model.Foo.t | nil } - alias OpenapiPetstore.Deserializer + @derive {JSON.Encoder, only: [:string]} + @primary_key false + embedded_schema do + embeds_one :string, OpenapiPetstore.Model.Foo + end - def decode(value) do - value - |> Deserializer.deserialize(:string, :struct, OpenapiPetstore.Model.Foo) + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, []) + |> Ecto.Changeset.validate_required([]) + |> Ecto.Changeset.cast_embed(:string) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/_special_model_name_.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/_special_model_name_.ex index eba15b56b98c..642505d60d9c 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/_special_model_name_.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/_special_model_name_.ex @@ -5,18 +5,23 @@ defmodule OpenapiPetstore.Model.SpecialModelName do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :"$special[property.name]" - ] + use Ecto.Schema @type t :: %__MODULE__{ :"$special[property.name]" => integer() | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:"$special[property.name]"]} + @primary_key false + embedded_schema do + field :"$special[property.name]", :integer + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:"$special[property.name]"]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/additional_properties_class.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/additional_properties_class.ex index 6ae586dbd68b..5ffc92bee1cf 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/additional_properties_class.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/additional_properties_class.ex @@ -5,20 +5,25 @@ defmodule OpenapiPetstore.Model.AdditionalPropertiesClass do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :map_property, - :map_of_map_property - ] + use Ecto.Schema @type t :: %__MODULE__{ :map_property => %{optional(String.t) => String.t} | nil, :map_of_map_property => %{optional(String.t) => %{optional(String.t) => String.t}} | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:map_property, :map_of_map_property]} + @primary_key false + embedded_schema do + field :map_property, :map + field :map_of_map_property, :map + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:map_property, :map_of_map_property]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/all_of_with_single_ref.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/all_of_with_single_ref.ex index 12c0fcc52169..aa6eade4786c 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/all_of_with_single_ref.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/all_of_with_single_ref.ex @@ -5,23 +5,26 @@ defmodule OpenapiPetstore.Model.AllOfWithSingleRef do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :username, - :SingleRefType - ] + use Ecto.Schema @type t :: %__MODULE__{ :username => String.t | nil, :SingleRefType => OpenapiPetstore.Model.SingleRefType.t | nil } - alias OpenapiPetstore.Deserializer + @derive {JSON.Encoder, only: [:username, :SingleRefType]} + @primary_key false + embedded_schema do + field :username, :string + embeds_one :SingleRefType, OpenapiPetstore.Model.SingleRefType + end - def decode(value) do - value - |> Deserializer.deserialize(:SingleRefType, :struct, OpenapiPetstore.Model.SingleRefType) + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:username]) + |> Ecto.Changeset.validate_required([]) + |> Ecto.Changeset.cast_embed(:SingleRefType) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/animal.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/animal.ex index 22b7ae317557..872257588005 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/animal.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/animal.ex @@ -5,20 +5,25 @@ defmodule OpenapiPetstore.Model.Animal do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :className, - :color - ] + use Ecto.Schema @type t :: %__MODULE__{ :className => String.t, :color => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:className, :color]} + @primary_key false + embedded_schema do + field :className, :string + field :color, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:className, :color]) + |> Ecto.Changeset.validate_required([:className]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/any.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/any.ex index 592ca5361366..0cad3c311356 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/any.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/any.ex @@ -5,18 +5,23 @@ defmodule OpenapiPetstore.Model.Any do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :"@type" - ] + use Ecto.Schema @type t :: %__MODULE__{ :"@type" => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:"@type"]} + @primary_key false + embedded_schema do + field :"@type", :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:"@type"]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/api_response.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/api_response.ex index 417217551270..4054e9e4c699 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/api_response.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/api_response.ex @@ -5,13 +5,7 @@ defmodule OpenapiPetstore.Model.ApiResponse do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :code, - :type, - :message - ] + use Ecto.Schema @type t :: %__MODULE__{ :code => integer() | nil, @@ -19,8 +13,19 @@ defmodule OpenapiPetstore.Model.ApiResponse do :message => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:code, :type, :message]} + @primary_key false + embedded_schema do + field :code, :integer + field :type, :string + field :message, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:code, :type, :message]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_array_of_number_only.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_array_of_number_only.ex index e64dafe87cb4..944fcc5be0e9 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_array_of_number_only.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_array_of_number_only.ex @@ -5,18 +5,23 @@ defmodule OpenapiPetstore.Model.ArrayOfArrayOfNumberOnly do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :ArrayArrayNumber - ] + use Ecto.Schema @type t :: %__MODULE__{ :ArrayArrayNumber => [[number()]] | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:ArrayArrayNumber]} + @primary_key false + embedded_schema do + field :ArrayArrayNumber, {:array, {:array, :float}} + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:ArrayArrayNumber]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_number_only.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_number_only.ex index 0e05e5aa8217..8fafd9c29842 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_number_only.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_number_only.ex @@ -5,18 +5,23 @@ defmodule OpenapiPetstore.Model.ArrayOfNumberOnly do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :ArrayNumber - ] + use Ecto.Schema @type t :: %__MODULE__{ :ArrayNumber => [number()] | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:ArrayNumber]} + @primary_key false + embedded_schema do + field :ArrayNumber, {:array, :float} + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:ArrayNumber]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/array_test.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/array_test.ex index 8524a5f9172f..1fd276fa8b68 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/array_test.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/array_test.ex @@ -5,13 +5,7 @@ defmodule OpenapiPetstore.Model.ArrayTest do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :array_of_string, - :array_array_of_integer, - :array_array_of_model - ] + use Ecto.Schema @type t :: %__MODULE__{ :array_of_string => [String.t] | nil, @@ -19,8 +13,19 @@ defmodule OpenapiPetstore.Model.ArrayTest do :array_array_of_model => [[OpenapiPetstore.Model.ReadOnlyFirst.t]] | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:array_of_string, :array_array_of_integer, :array_array_of_model]} + @primary_key false + embedded_schema do + field :array_of_string, {:array, :string} + field :array_array_of_integer, {:array, {:array, :integer}} + field :array_array_of_model, {:array, {:array, :any}} + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:array_of_string, :array_array_of_integer, :array_array_of_model]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/capitalization.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/capitalization.ex index 172f74c9ca6c..5169515612c6 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/capitalization.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/capitalization.ex @@ -5,16 +5,7 @@ defmodule OpenapiPetstore.Model.Capitalization do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :smallCamel, - :CapitalCamel, - :small_Snake, - :Capital_Snake, - :SCA_ETH_Flow_Points, - :ATT_NAME - ] + use Ecto.Schema @type t :: %__MODULE__{ :smallCamel => String.t | nil, @@ -25,8 +16,22 @@ defmodule OpenapiPetstore.Model.Capitalization do :ATT_NAME => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:smallCamel, :CapitalCamel, :small_Snake, :Capital_Snake, :SCA_ETH_Flow_Points, :ATT_NAME]} + @primary_key false + embedded_schema do + field :smallCamel, :string + field :CapitalCamel, :string + field :small_Snake, :string + field :Capital_Snake, :string + field :SCA_ETH_Flow_Points, :string + field :ATT_NAME, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:smallCamel, :CapitalCamel, :small_Snake, :Capital_Snake, :SCA_ETH_Flow_Points, :ATT_NAME]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/cat.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/cat.ex index 6baa323232a1..fb593c520df6 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/cat.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/cat.ex @@ -5,13 +5,7 @@ defmodule OpenapiPetstore.Model.Cat do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :className, - :color, - :declawed - ] + use Ecto.Schema @type t :: %__MODULE__{ :className => String.t, @@ -19,8 +13,19 @@ defmodule OpenapiPetstore.Model.Cat do :declawed => boolean() | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:className, :color, :declawed]} + @primary_key false + embedded_schema do + field :className, :string + field :color, :string + field :declawed, :boolean + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:className, :color, :declawed]) + |> Ecto.Changeset.validate_required([:className]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/category.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/category.ex index a3d46d051705..42efd3cc7d5b 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/category.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/category.ex @@ -5,20 +5,25 @@ defmodule OpenapiPetstore.Model.Category do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :id, - :name - ] + use Ecto.Schema @type t :: %__MODULE__{ :id => integer() | nil, :name => String.t } - def decode(value) do - value + @derive {JSON.Encoder, only: [:id, :name]} + @primary_key false + embedded_schema do + field :id, :integer + field :name, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:id, :name]) + |> Ecto.Changeset.validate_required([:name]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/child_with_nullable.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/child_with_nullable.ex index a4e95a253292..c0e46d1f4726 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/child_with_nullable.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/child_with_nullable.ex @@ -5,13 +5,7 @@ defmodule OpenapiPetstore.Model.ChildWithNullable do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :type, - :nullableProperty, - :otherProperty - ] + use Ecto.Schema @type t :: %__MODULE__{ :type => String.t | nil, @@ -19,8 +13,19 @@ defmodule OpenapiPetstore.Model.ChildWithNullable do :otherProperty => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:type, :nullableProperty, :otherProperty]} + @primary_key false + embedded_schema do + field :type, :string + field :nullableProperty, :string + field :otherProperty, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:type, :nullableProperty, :otherProperty]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/class_model.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/class_model.ex index b557aa165f5a..6e37614a15d6 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/class_model.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/class_model.ex @@ -5,18 +5,23 @@ defmodule OpenapiPetstore.Model.ClassModel do @moduledoc """ Model for testing model with \"_class\" property """ - - @derive JSON.Encoder - defstruct [ - :_class - ] + use Ecto.Schema @type t :: %__MODULE__{ :_class => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:_class]} + @primary_key false + embedded_schema do + field :_class, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:_class]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/client.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/client.ex index 6becddde7adb..262f88713b7c 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/client.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/client.ex @@ -5,18 +5,23 @@ defmodule OpenapiPetstore.Model.Client do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :client - ] + use Ecto.Schema @type t :: %__MODULE__{ :client => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:client]} + @primary_key false + embedded_schema do + field :client, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:client]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/deprecated_model.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/deprecated_model.ex index 3c53570d198e..ac45e9aed5e7 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/deprecated_model.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/deprecated_model.ex @@ -5,18 +5,23 @@ defmodule OpenapiPetstore.Model.DeprecatedModel do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :name - ] + use Ecto.Schema @type t :: %__MODULE__{ :name => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:name]} + @primary_key false + embedded_schema do + field :name, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:name]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/dog.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/dog.ex index ccf2920a7115..79e2b8c12931 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/dog.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/dog.ex @@ -5,13 +5,7 @@ defmodule OpenapiPetstore.Model.Dog do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :className, - :color, - :breed - ] + use Ecto.Schema @type t :: %__MODULE__{ :className => String.t, @@ -19,8 +13,19 @@ defmodule OpenapiPetstore.Model.Dog do :breed => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:className, :color, :breed]} + @primary_key false + embedded_schema do + field :className, :string + field :color, :string + field :breed, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:className, :color, :breed]) + |> Ecto.Changeset.validate_required([:className]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_arrays.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_arrays.ex index 74f5c3515413..70819831c235 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_arrays.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_arrays.ex @@ -5,20 +5,25 @@ defmodule OpenapiPetstore.Model.EnumArrays do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :just_symbol, - :array_enum - ] + use Ecto.Schema @type t :: %__MODULE__{ :just_symbol => String.t | nil, :array_enum => [String.t] | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:just_symbol, :array_enum]} + @primary_key false + embedded_schema do + field :just_symbol, :string + field :array_enum, {:array, :string} + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:just_symbol, :array_enum]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_class.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_class.ex index e9734a963a8c..5e661c1648a4 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_class.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_class.ex @@ -5,18 +5,22 @@ defmodule OpenapiPetstore.Model.EnumClass do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - - ] + use Ecto.Schema @type t :: %__MODULE__{ } - def decode(value) do - value + @derive {JSON.Encoder, only: []} + @primary_key false + embedded_schema do + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, []) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_test.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_test.ex index de92b07b1f78..932cb367a49a 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_test.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_test.ex @@ -5,18 +5,7 @@ defmodule OpenapiPetstore.Model.EnumTest do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :enum_string, - :enum_string_required, - :enum_integer, - :enum_number, - :outerEnum, - :outerEnumInteger, - :outerEnumDefaultValue, - :outerEnumIntegerDefaultValue - ] + use Ecto.Schema @type t :: %__MODULE__{ :enum_string => String.t | nil, @@ -29,14 +18,28 @@ defmodule OpenapiPetstore.Model.EnumTest do :outerEnumIntegerDefaultValue => OpenapiPetstore.Model.OuterEnumIntegerDefaultValue.t | nil } - alias OpenapiPetstore.Deserializer + @derive {JSON.Encoder, only: [:enum_string, :enum_string_required, :enum_integer, :enum_number, :outerEnum, :outerEnumInteger, :outerEnumDefaultValue, :outerEnumIntegerDefaultValue]} + @primary_key false + embedded_schema do + field :enum_string, :string + field :enum_string_required, :string + field :enum_integer, :integer + field :enum_number, :float + embeds_one :outerEnum, OpenapiPetstore.Model.OuterEnum + embeds_one :outerEnumInteger, OpenapiPetstore.Model.OuterEnumInteger + embeds_one :outerEnumDefaultValue, OpenapiPetstore.Model.OuterEnumDefaultValue + embeds_one :outerEnumIntegerDefaultValue, OpenapiPetstore.Model.OuterEnumIntegerDefaultValue + end - def decode(value) do - value - |> Deserializer.deserialize(:outerEnum, :struct, OpenapiPetstore.Model.OuterEnum) - |> Deserializer.deserialize(:outerEnumInteger, :struct, OpenapiPetstore.Model.OuterEnumInteger) - |> Deserializer.deserialize(:outerEnumDefaultValue, :struct, OpenapiPetstore.Model.OuterEnumDefaultValue) - |> Deserializer.deserialize(:outerEnumIntegerDefaultValue, :struct, OpenapiPetstore.Model.OuterEnumIntegerDefaultValue) + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:enum_string, :enum_string_required, :enum_integer, :enum_number]) + |> Ecto.Changeset.validate_required([:enum_string_required]) + |> Ecto.Changeset.cast_embed(:outerEnum) + |> Ecto.Changeset.cast_embed(:outerEnumInteger) + |> Ecto.Changeset.cast_embed(:outerEnumDefaultValue) + |> Ecto.Changeset.cast_embed(:outerEnumIntegerDefaultValue) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/fake_big_decimal_map_200_response.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/fake_big_decimal_map_200_response.ex index ba9f8e5d44ba..75602eeec9ed 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/fake_big_decimal_map_200_response.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/fake_big_decimal_map_200_response.ex @@ -5,20 +5,25 @@ defmodule OpenapiPetstore.Model.FakeBigDecimalMap200Response do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :someId, - :someMap - ] + use Ecto.Schema @type t :: %__MODULE__{ :someId => number() | nil, :someMap => %{optional(String.t) => number()} | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:someId, :someMap]} + @primary_key false + embedded_schema do + field :someId, :float + field :someMap, :map + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:someId, :someMap]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/file.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/file.ex index 78cff001f1c1..2e1ce62b69cb 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/file.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/file.ex @@ -5,18 +5,23 @@ defmodule OpenapiPetstore.Model.File do @moduledoc """ Must be named `File` for test. """ - - @derive JSON.Encoder - defstruct [ - :sourceURI - ] + use Ecto.Schema @type t :: %__MODULE__{ :sourceURI => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:sourceURI]} + @primary_key false + embedded_schema do + field :sourceURI, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:sourceURI]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/file_schema_test_class.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/file_schema_test_class.ex index 3decf1dbadf2..74059653dbe6 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/file_schema_test_class.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/file_schema_test_class.ex @@ -5,24 +5,27 @@ defmodule OpenapiPetstore.Model.FileSchemaTestClass do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :file, - :files - ] + use Ecto.Schema @type t :: %__MODULE__{ :file => OpenapiPetstore.Model.File.t | nil, :files => [OpenapiPetstore.Model.File.t] | nil } - alias OpenapiPetstore.Deserializer + @derive {JSON.Encoder, only: [:file, :files]} + @primary_key false + embedded_schema do + embeds_one :file, OpenapiPetstore.Model.File + embeds_many :files, OpenapiPetstore.Model.File + end - def decode(value) do - value - |> Deserializer.deserialize(:file, :struct, OpenapiPetstore.Model.File) - |> Deserializer.deserialize(:files, :list, OpenapiPetstore.Model.File) + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, []) + |> Ecto.Changeset.validate_required([]) + |> Ecto.Changeset.cast_embed(:file) + |> Ecto.Changeset.cast_embed(:files) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/foo.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/foo.ex index 1319347382bf..ca428f064597 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/foo.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/foo.ex @@ -5,18 +5,23 @@ defmodule OpenapiPetstore.Model.Foo do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :bar - ] + use Ecto.Schema @type t :: %__MODULE__{ :bar => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:bar]} + @primary_key false + embedded_schema do + field :bar, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:bar]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/format_test.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/format_test.ex index a71b6eb59df7..ab57679ce007 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/format_test.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/format_test.ex @@ -5,26 +5,7 @@ defmodule OpenapiPetstore.Model.FormatTest do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :integer, - :int32, - :int64, - :number, - :float, - :double, - :decimal, - :string, - :byte, - :binary, - :date, - :dateTime, - :uuid, - :password, - :pattern_with_digits, - :pattern_with_digits_and_delimiter - ] + use Ecto.Schema @type t :: %__MODULE__{ :integer => integer() | nil, @@ -45,8 +26,32 @@ defmodule OpenapiPetstore.Model.FormatTest do :pattern_with_digits_and_delimiter => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:integer, :int32, :int64, :number, :float, :double, :decimal, :string, :byte, :binary, :date, :dateTime, :uuid, :password, :pattern_with_digits, :pattern_with_digits_and_delimiter]} + @primary_key false + embedded_schema do + field :integer, :integer + field :int32, :integer + field :int64, :integer + field :number, :float + field :float, :float + field :double, :float + field :decimal, :float + field :string, :string + field :byte, :binary + field :binary, :string + field :date, :date + field :dateTime, :utc_datetime + field :uuid, :string + field :password, :string + field :pattern_with_digits, :string + field :pattern_with_digits_and_delimiter, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:integer, :int32, :int64, :number, :float, :double, :decimal, :string, :byte, :binary, :date, :dateTime, :uuid, :password, :pattern_with_digits, :pattern_with_digits_and_delimiter]) + |> Ecto.Changeset.validate_required([:number, :byte, :date, :password]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/has_only_read_only.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/has_only_read_only.ex index 54d5751bbeee..e14d62f4beef 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/has_only_read_only.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/has_only_read_only.ex @@ -5,20 +5,25 @@ defmodule OpenapiPetstore.Model.HasOnlyReadOnly do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :bar, - :foo - ] + use Ecto.Schema @type t :: %__MODULE__{ :bar => String.t | nil, :foo => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:bar, :foo]} + @primary_key false + embedded_schema do + field :bar, :string + field :foo, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:bar, :foo]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/health_check_result.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/health_check_result.ex index ec53b4fd2c3a..95d593f8f735 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/health_check_result.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/health_check_result.ex @@ -5,18 +5,23 @@ defmodule OpenapiPetstore.Model.HealthCheckResult do @moduledoc """ Just a string to inform instance is up and running. Make it nullable in hope to get it as pointer in generated model. """ - - @derive JSON.Encoder - defstruct [ - :NullableMessage - ] + use Ecto.Schema @type t :: %__MODULE__{ :NullableMessage => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:NullableMessage]} + @primary_key false + embedded_schema do + field :NullableMessage, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:NullableMessage]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/list.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/list.ex index 4bdf858c5aaf..a5161edbd44c 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/list.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/list.ex @@ -5,18 +5,23 @@ defmodule OpenapiPetstore.Model.List do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :"123-list" - ] + use Ecto.Schema @type t :: %__MODULE__{ :"123-list" => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:"123-list"]} + @primary_key false + embedded_schema do + field :"123-list", :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:"123-list"]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex index 378716903a44..9ea5e2a4583a 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex @@ -5,14 +5,7 @@ defmodule OpenapiPetstore.Model.MapTest do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :map_map_of_string, - :map_of_enum_string, - :direct_map, - :indirect_map - ] + use Ecto.Schema @type t :: %__MODULE__{ :map_map_of_string => %{optional(String.t) => %{optional(String.t) => String.t}} | nil, @@ -21,8 +14,20 @@ defmodule OpenapiPetstore.Model.MapTest do :indirect_map => %{optional(String.t) => boolean()} | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:map_map_of_string, :map_of_enum_string, :direct_map, :indirect_map]} + @primary_key false + embedded_schema do + field :map_map_of_string, :map + field :map_of_enum_string, :map + field :direct_map, :map + field :indirect_map, :map + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:map_map_of_string, :map_of_enum_string, :direct_map, :indirect_map]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex index 264980e41667..e8d3561adfe8 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex @@ -5,13 +5,7 @@ defmodule OpenapiPetstore.Model.MixedPropertiesAndAdditionalPropertiesClass do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :uuid, - :dateTime, - :map - ] + use Ecto.Schema @type t :: %__MODULE__{ :uuid => String.t | nil, @@ -19,11 +13,19 @@ defmodule OpenapiPetstore.Model.MixedPropertiesAndAdditionalPropertiesClass do :map => %{optional(String.t) => OpenapiPetstore.Model.Animal.t} | nil } - alias OpenapiPetstore.Deserializer + @derive {JSON.Encoder, only: [:uuid, :dateTime, :map]} + @primary_key false + embedded_schema do + field :uuid, :string + field :dateTime, :utc_datetime + field :map, :map + end - def decode(value) do - value - |> Deserializer.deserialize(:map, :map, OpenapiPetstore.Model.Animal) + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:uuid, :dateTime, :map]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/model_200_response.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/model_200_response.ex index 2c460b20a3b6..168ea59a311b 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/model_200_response.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/model_200_response.ex @@ -5,20 +5,25 @@ defmodule OpenapiPetstore.Model.Model200Response do @moduledoc """ Model for testing model name starting with number """ - - @derive JSON.Encoder - defstruct [ - :name, - :class - ] + use Ecto.Schema @type t :: %__MODULE__{ :name => integer() | nil, :class => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:name, :class]} + @primary_key false + embedded_schema do + field :name, :integer + field :class, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:name, :class]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/name.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/name.ex index 7b56dae6cd17..1c430671a640 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/name.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/name.ex @@ -5,14 +5,7 @@ defmodule OpenapiPetstore.Model.Name do @moduledoc """ Model for testing model name same as property name """ - - @derive JSON.Encoder - defstruct [ - :name, - :snake_case, - :property, - :"123Number" - ] + use Ecto.Schema @type t :: %__MODULE__{ :name => integer(), @@ -21,8 +14,20 @@ defmodule OpenapiPetstore.Model.Name do :"123Number" => integer() | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:name, :snake_case, :property, :"123Number"]} + @primary_key false + embedded_schema do + field :name, :integer + field :snake_case, :integer + field :property, :string + field :"123Number", :integer + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:name, :snake_case, :property, :"123Number"]) + |> Ecto.Changeset.validate_required([:name]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/nullable_class.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/nullable_class.ex index a6a86dd702ff..905700b798bc 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/nullable_class.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/nullable_class.ex @@ -5,22 +5,7 @@ defmodule OpenapiPetstore.Model.NullableClass do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :integer_prop, - :number_prop, - :boolean_prop, - :string_prop, - :date_prop, - :datetime_prop, - :array_nullable_prop, - :array_and_items_nullable_prop, - :array_items_nullable, - :object_nullable_prop, - :object_and_items_nullable_prop, - :object_items_nullable - ] + use Ecto.Schema @type t :: %__MODULE__{ :integer_prop => integer() | nil, @@ -37,8 +22,28 @@ defmodule OpenapiPetstore.Model.NullableClass do :object_items_nullable => %{optional(String.t) => map()} | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:integer_prop, :number_prop, :boolean_prop, :string_prop, :date_prop, :datetime_prop, :array_nullable_prop, :array_and_items_nullable_prop, :array_items_nullable, :object_nullable_prop, :object_and_items_nullable_prop, :object_items_nullable]} + @primary_key false + embedded_schema do + field :integer_prop, :integer + field :number_prop, :float + field :boolean_prop, :boolean + field :string_prop, :string + field :date_prop, :date + field :datetime_prop, :utc_datetime + field :array_nullable_prop, {:array, :map} + field :array_and_items_nullable_prop, {:array, :map} + field :array_items_nullable, {:array, :map} + field :object_nullable_prop, :map + field :object_and_items_nullable_prop, :map + field :object_items_nullable, :map + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:integer_prop, :number_prop, :boolean_prop, :string_prop, :date_prop, :datetime_prop, :array_nullable_prop, :array_and_items_nullable_prop, :array_items_nullable, :object_nullable_prop, :object_and_items_nullable_prop, :object_items_nullable]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/number_only.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/number_only.ex index d979c8d8535c..574db1a05a4a 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/number_only.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/number_only.ex @@ -5,18 +5,23 @@ defmodule OpenapiPetstore.Model.NumberOnly do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :JustNumber - ] + use Ecto.Schema @type t :: %__MODULE__{ :JustNumber => number() | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:JustNumber]} + @primary_key false + embedded_schema do + field :JustNumber, :float + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:JustNumber]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/object_with_deprecated_fields.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/object_with_deprecated_fields.ex index d92923d6c693..3a46ee417bff 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/object_with_deprecated_fields.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/object_with_deprecated_fields.ex @@ -5,14 +5,7 @@ defmodule OpenapiPetstore.Model.ObjectWithDeprecatedFields do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :uuid, - :id, - :deprecatedRef, - :bars - ] + use Ecto.Schema @type t :: %__MODULE__{ :uuid => String.t | nil, @@ -21,11 +14,21 @@ defmodule OpenapiPetstore.Model.ObjectWithDeprecatedFields do :bars => [String.t] | nil } - alias OpenapiPetstore.Deserializer + @derive {JSON.Encoder, only: [:uuid, :id, :deprecatedRef, :bars]} + @primary_key false + embedded_schema do + field :uuid, :string + field :id, :float + field :bars, {:array, :string} + embeds_one :deprecatedRef, OpenapiPetstore.Model.DeprecatedModel + end - def decode(value) do - value - |> Deserializer.deserialize(:deprecatedRef, :struct, OpenapiPetstore.Model.DeprecatedModel) + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:uuid, :id, :bars]) + |> Ecto.Changeset.validate_required([]) + |> Ecto.Changeset.cast_embed(:deprecatedRef) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/order.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/order.ex index e78a131855a1..491c498f7149 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/order.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/order.ex @@ -5,16 +5,7 @@ defmodule OpenapiPetstore.Model.Order do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :id, - :petId, - :quantity, - :shipDate, - :status, - :complete - ] + use Ecto.Schema @type t :: %__MODULE__{ :id => integer() | nil, @@ -25,8 +16,22 @@ defmodule OpenapiPetstore.Model.Order do :complete => boolean() | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:id, :petId, :quantity, :shipDate, :status, :complete]} + @primary_key false + embedded_schema do + field :id, :integer + field :petId, :integer + field :quantity, :integer + field :shipDate, :utc_datetime + field :status, :string + field :complete, :boolean + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:id, :petId, :quantity, :shipDate, :status, :complete]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_composite.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_composite.ex index a9c9607114a1..c153094d7299 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_composite.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_composite.ex @@ -5,13 +5,7 @@ defmodule OpenapiPetstore.Model.OuterComposite do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :my_number, - :my_string, - :my_boolean - ] + use Ecto.Schema @type t :: %__MODULE__{ :my_number => number() | nil, @@ -19,8 +13,19 @@ defmodule OpenapiPetstore.Model.OuterComposite do :my_boolean => boolean() | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:my_number, :my_string, :my_boolean]} + @primary_key false + embedded_schema do + field :my_number, :float + field :my_string, :string + field :my_boolean, :boolean + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:my_number, :my_string, :my_boolean]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum.ex index 7c43a9606d26..4b878199f396 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum.ex @@ -5,18 +5,22 @@ defmodule OpenapiPetstore.Model.OuterEnum do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - - ] + use Ecto.Schema @type t :: %__MODULE__{ } - def decode(value) do - value + @derive {JSON.Encoder, only: []} + @primary_key false + embedded_schema do + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, []) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_default_value.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_default_value.ex index f5e885c029eb..818f8b77b0a2 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_default_value.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_default_value.ex @@ -5,18 +5,22 @@ defmodule OpenapiPetstore.Model.OuterEnumDefaultValue do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - - ] + use Ecto.Schema @type t :: %__MODULE__{ } - def decode(value) do - value + @derive {JSON.Encoder, only: []} + @primary_key false + embedded_schema do + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, []) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer.ex index 5cc18b611dec..c06d74991b82 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer.ex @@ -5,18 +5,22 @@ defmodule OpenapiPetstore.Model.OuterEnumInteger do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - - ] + use Ecto.Schema @type t :: %__MODULE__{ } - def decode(value) do - value + @derive {JSON.Encoder, only: []} + @primary_key false + embedded_schema do + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, []) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer_default_value.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer_default_value.ex index 04609d34f94c..19767ff3fd32 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer_default_value.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer_default_value.ex @@ -5,18 +5,22 @@ defmodule OpenapiPetstore.Model.OuterEnumIntegerDefaultValue do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - - ] + use Ecto.Schema @type t :: %__MODULE__{ } - def decode(value) do - value + @derive {JSON.Encoder, only: []} + @primary_key false + embedded_schema do + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, []) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_object_with_enum_property.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_object_with_enum_property.ex index 774fd01e65fb..2bca96bea61b 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_object_with_enum_property.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_object_with_enum_property.ex @@ -5,21 +5,24 @@ defmodule OpenapiPetstore.Model.OuterObjectWithEnumProperty do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :value - ] + use Ecto.Schema @type t :: %__MODULE__{ :value => OpenapiPetstore.Model.OuterEnumInteger.t } - alias OpenapiPetstore.Deserializer + @derive {JSON.Encoder, only: [:value]} + @primary_key false + embedded_schema do + embeds_one :value, OpenapiPetstore.Model.OuterEnumInteger + end - def decode(value) do - value - |> Deserializer.deserialize(:value, :struct, OpenapiPetstore.Model.OuterEnumInteger) + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, []) + |> Ecto.Changeset.validate_required([]) + |> Ecto.Changeset.cast_embed(:value, required: true) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/parent_with_nullable.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/parent_with_nullable.ex index 2e33e0b8bd85..6a726f09d846 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/parent_with_nullable.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/parent_with_nullable.ex @@ -5,20 +5,25 @@ defmodule OpenapiPetstore.Model.ParentWithNullable do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :type, - :nullableProperty - ] + use Ecto.Schema @type t :: %__MODULE__{ :type => String.t | nil, :nullableProperty => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:type, :nullableProperty]} + @primary_key false + embedded_schema do + field :type, :string + field :nullableProperty, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:type, :nullableProperty]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex index ed8da6940054..58f267be1d04 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex @@ -5,16 +5,7 @@ defmodule OpenapiPetstore.Model.Pet do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :id, - :category, - :name, - :photoUrls, - :tags, - :status - ] + use Ecto.Schema @type t :: %__MODULE__{ :id => integer() | nil, @@ -25,12 +16,25 @@ defmodule OpenapiPetstore.Model.Pet do :status => String.t | nil } - alias OpenapiPetstore.Deserializer + @derive {JSON.Encoder, only: [:id, :category, :name, :photoUrls, :tags, :status]} + @primary_key false + embedded_schema do + field :id, :integer + field :name, :string + field :photoUrls, :any, virtual: true + embeds_many :tags, OpenapiPetstore.Model.Tag + field :status, :string + embeds_one :category, OpenapiPetstore.Model.Category + embeds_many :tags, OpenapiPetstore.Model.Tag + end - def decode(value) do - value - |> Deserializer.deserialize(:category, :struct, OpenapiPetstore.Model.Category) - |> Deserializer.deserialize(:tags, :list, OpenapiPetstore.Model.Tag) + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:id, :name, :photoUrls, :status]) + |> Ecto.Changeset.validate_required([:name, :photoUrls]) + |> Ecto.Changeset.cast_embed(:category) + |> Ecto.Changeset.cast_embed(:tags) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/read_only_first.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/read_only_first.ex index fbee5d093f5e..14cfb6da5c3d 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/read_only_first.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/read_only_first.ex @@ -5,20 +5,25 @@ defmodule OpenapiPetstore.Model.ReadOnlyFirst do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :bar, - :baz - ] + use Ecto.Schema @type t :: %__MODULE__{ :bar => String.t | nil, :baz => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:bar, :baz]} + @primary_key false + embedded_schema do + field :bar, :string + field :baz, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:bar, :baz]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/return.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/return.ex index 3077af6f0f10..ce7dbdd46b4c 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/return.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/return.ex @@ -5,18 +5,23 @@ defmodule OpenapiPetstore.Model.Return do @moduledoc """ Model for testing reserved words """ - - @derive JSON.Encoder - defstruct [ - :return - ] + use Ecto.Schema @type t :: %__MODULE__{ :return => integer() | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:return]} + @primary_key false + embedded_schema do + field :return, :integer + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:return]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/single_ref_type.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/single_ref_type.ex index c89f2270ebbe..f5bc6cc7575a 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/single_ref_type.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/single_ref_type.ex @@ -5,18 +5,22 @@ defmodule OpenapiPetstore.Model.SingleRefType do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - - ] + use Ecto.Schema @type t :: %__MODULE__{ } - def decode(value) do - value + @derive {JSON.Encoder, only: []} + @primary_key false + embedded_schema do + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, []) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/tag.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/tag.ex index 3df03aa64d45..62a1a2059a46 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/tag.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/tag.ex @@ -5,20 +5,25 @@ defmodule OpenapiPetstore.Model.Tag do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :id, - :name - ] + use Ecto.Schema @type t :: %__MODULE__{ :id => integer() | nil, :name => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:id, :name]} + @primary_key false + embedded_schema do + field :id, :integer + field :name, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:id, :name]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/test_inline_freeform_additional_properties_request.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/test_inline_freeform_additional_properties_request.ex index da536af364cd..601ceedb5973 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/test_inline_freeform_additional_properties_request.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/test_inline_freeform_additional_properties_request.ex @@ -5,18 +5,23 @@ defmodule OpenapiPetstore.Model.TestInlineFreeformAdditionalPropertiesRequest do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :someProperty - ] + use Ecto.Schema @type t :: %__MODULE__{ :someProperty => String.t | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:someProperty]} + @primary_key false + embedded_schema do + field :someProperty, :string + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:someProperty]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/user.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/user.ex index 02e1850f1297..78eded1e95de 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/user.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/user.ex @@ -5,18 +5,7 @@ defmodule OpenapiPetstore.Model.User do @moduledoc """ """ - - @derive JSON.Encoder - defstruct [ - :id, - :username, - :firstName, - :lastName, - :email, - :password, - :phone, - :userStatus - ] + use Ecto.Schema @type t :: %__MODULE__{ :id => integer() | nil, @@ -29,8 +18,24 @@ defmodule OpenapiPetstore.Model.User do :userStatus => integer() | nil } - def decode(value) do - value + @derive {JSON.Encoder, only: [:id, :username, :firstName, :lastName, :email, :password, :phone, :userStatus]} + @primary_key false + embedded_schema do + field :id, :integer + field :username, :string + field :firstName, :string + field :lastName, :string + field :email, :string + field :password, :string + field :phone, :string + field :userStatus, :integer + end + + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(%__MODULE__{} = struct, params) do + struct + |> Ecto.Changeset.cast(params, [:id, :username, :firstName, :lastName, :email, :password, :phone, :userStatus]) + |> Ecto.Changeset.validate_required([]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/request_builder.ex b/samples/client/petstore/elixir/lib/openapi_petstore/request_builder.ex index 640b1a05cfe8..7e62461435ee 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/request_builder.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/request_builder.ex @@ -189,10 +189,26 @@ defmodule OpenapiPetstore.RequestBuilder do defp decode(%Tesla.Env{} = env, false), do: {:ok, env} defp decode(%Tesla.Env{body: body}, %{}) do - OpenapiPetstore.Deserializer.json_decode(body) + JSON.decode(body) end defp decode(%Tesla.Env{body: body}, module) do - OpenapiPetstore.Deserializer.json_decode(body, module) + case JSON.decode(body) do + {:ok, objects} when is_list(objects) -> + models = Enum.map(objects, fn object -> + {:ok, model} = to_model(module, object) + model + end) + {:ok, models} + {:ok, params} -> to_model(module, params) + {:error, error} -> {:error, error} + end + end + + defp to_model(module, params) do + module + |> struct + |> module.changeset(params) + |> Ecto.Changeset.apply_action(:insert) end end diff --git a/samples/client/petstore/elixir/mix.exs b/samples/client/petstore/elixir/mix.exs index 63a3eb9d83ef..49d027b21e06 100644 --- a/samples/client/petstore/elixir/mix.exs +++ b/samples/client/petstore/elixir/mix.exs @@ -35,6 +35,7 @@ defmodule OpenapiPetstore.Mixfile do # Type "mix help deps" for more examples and options defp deps do [ + {:ecto, "~> 3.12"}, {:tesla, "~> 1.14"}, {:ex_doc, "~> 0.37.3", only: :dev, runtime: false}, {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false} diff --git a/samples/client/petstore/elixir/test/outer_enum_test.exs b/samples/client/petstore/elixir/test/outer_enum_test.exs index b193b5f85816..57dc65974ea9 100644 --- a/samples/client/petstore/elixir/test/outer_enum_test.exs +++ b/samples/client/petstore/elixir/test/outer_enum_test.exs @@ -1,7 +1,6 @@ defmodule OuterEnumTest do use ExUnit.Case, async: true - alias OpenapiPetstore.Deserializer alias OpenapiPetstore.Model.EnumTest @valid_json """ @@ -15,13 +14,17 @@ defmodule OuterEnumTest do @tag timeout: :infinity test "json_decode/2 with valid JSON" do - assert Deserializer.json_decode(@valid_json, EnumTest) == - {:ok, - %EnumTest{ - enum_string: "UPPER", - enum_number: 1.1, - outerEnum: "placed", - outerEnumInteger: 1 - }} + enum_test = + JSON.decode!(@valid_json) + |> then(fn params -> EnumTest.changeset(%EnumTest{}, params) end) + |> Ecto.Changeset.apply_action!(:insert) + + assert enum_test == + %EnumTest{ + enum_string: "UPPER", + enum_number: 1.1, + outerEnum: "placed", + outerEnumInteger: 1 + } end end From eb673c742d7c9c7f0b322875006d52409ea0a730 Mon Sep 17 00:00:00 2001 From: Enrique Fernandez Date: Sun, 4 May 2025 23:15:08 +0200 Subject: [PATCH 2/9] fix: missing type mapping --- .../org/openapitools/codegen/languages/ElixirClientCodegen.java | 1 + .../client/petstore/elixir/lib/openapi_petstore/model/pet.ex | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java index 9b3072e2c540..eb9776d4f1cb 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java @@ -204,6 +204,7 @@ public ElixirClientCodegen() { typeMapping.put("integer", "integer()"); typeMapping.put("boolean", "boolean()"); typeMapping.put("array", "list()"); + typeMapping.put("set", "list()"); typeMapping.put("object", "map()"); typeMapping.put("map", "map()"); typeMapping.put("null", "nil"); diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex index 58f267be1d04..219c72718582 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex @@ -21,7 +21,7 @@ defmodule OpenapiPetstore.Model.Pet do embedded_schema do field :id, :integer field :name, :string - field :photoUrls, :any, virtual: true + field :photoUrls, {:array, :string} embeds_many :tags, OpenapiPetstore.Model.Tag field :status, :string embeds_one :category, OpenapiPetstore.Model.Category From 7f4e885f1976d61eb034ec9914e4a48cfbf478aa Mon Sep 17 00:00:00 2001 From: Enrique Fernandez Date: Tue, 6 May 2025 18:54:07 +0200 Subject: [PATCH 3/9] chore: update tests --- .../client/petstore/elixir/test/any_test.exs | 5 +-- .../elixir/test/deserializer_test.exs | 32 ++++++++++--------- .../petstore/elixir/test/format_test.exs | 18 ++++++----- ...s_and_additional_properties_class_test.exs | 12 ++++--- 4 files changed, 37 insertions(+), 30 deletions(-) diff --git a/samples/client/petstore/elixir/test/any_test.exs b/samples/client/petstore/elixir/test/any_test.exs index de9b3e095b4d..527d1600a57a 100644 --- a/samples/client/petstore/elixir/test/any_test.exs +++ b/samples/client/petstore/elixir/test/any_test.exs @@ -3,10 +3,11 @@ defmodule AnyTest do alias OpenapiPetstore.Model.Any, as: Model test "decode all properties (not nil)" do - assert %Model{ + assert %{ "@type": "3fa85f64-5717-4562-b3fc-2c963f66afa6" } - |> Model.decode() == + |> then(fn params -> Model.changeset(%Model{}, params) end) + |> Ecto.Changeset.apply_action!(:insert) == %Model{ "@type": "3fa85f64-5717-4562-b3fc-2c963f66afa6" } diff --git a/samples/client/petstore/elixir/test/deserializer_test.exs b/samples/client/petstore/elixir/test/deserializer_test.exs index d828974b7a5c..41498e64ac1d 100644 --- a/samples/client/petstore/elixir/test/deserializer_test.exs +++ b/samples/client/petstore/elixir/test/deserializer_test.exs @@ -1,6 +1,5 @@ defmodule DeserializerTest do use ExUnit.Case, async: true - alias OpenapiPetstore.Deserializer alias OpenapiPetstore.Model.{Category, Pet, Tag} @valid_json """ @@ -29,21 +28,24 @@ defmodule DeserializerTest do } """ - test "jason_decode/2 with valid JSON" do - assert Deserializer.json_decode(@valid_json, Pet) == - {:ok, - %Pet{ - id: 14, - category: %Category{id: 75, name: "sea dragons"}, - name: "Nagga", - photoUrls: ["https://example.com/nagga1.jpg", "https://example.com/nagga2.jpg"], - tags: [%Tag{id: 99, name: "dragon"}, %Tag{id: 23, name: "sea"}], - status: "foo" - }} + test "can deserialize valid JSON" do + pet = + JSON.decode!(@valid_json) + |> then(fn params -> Pet.changeset(%Pet{}, params) end) + |> Ecto.Changeset.apply_action!(:insert) + + assert pet == + %Pet{ + id: 14, + category: %Category{id: 75, name: "sea dragons"}, + name: "Nagga", + photoUrls: ["https://example.com/nagga1.jpg", "https://example.com/nagga2.jpg"], + tags: [%Tag{id: 99, name: "dragon"}, %Tag{id: 23, name: "sea"}], + status: "foo" + } end - test "jason_decode/2 with invalid JSON" do - assert Deserializer.json_decode(~s/{: 1}/, Pet) == - {:error, {:invalid_byte, 1, 58}} + test "cannot deserialize invalid JSON" do + assert JSON.decode(~s/{: 1}/) == {:error, {:invalid_byte, 1, 58}} end end diff --git a/samples/client/petstore/elixir/test/format_test.exs b/samples/client/petstore/elixir/test/format_test.exs index aa896b855223..c1951a5b375a 100644 --- a/samples/client/petstore/elixir/test/format_test.exs +++ b/samples/client/petstore/elixir/test/format_test.exs @@ -3,7 +3,7 @@ defmodule FormatTest do alias OpenapiPetstore.Model.FormatTest test "decode all properties (not nil)" do - assert %FormatTest{ + assert %{ integer: 1, int32: 2, int64: 3, @@ -21,7 +21,8 @@ defmodule FormatTest do pattern_with_digits: "1234567890", pattern_with_digits_and_delimiter: "Image_01" } - |> FormatTest.decode() == + |> then(fn params -> FormatTest.changeset(%FormatTest{}, params) end) + |> Ecto.Changeset.apply_action!(:insert) == %FormatTest{ integer: 1, int32: 2, @@ -29,12 +30,12 @@ defmodule FormatTest do number: 4.1, float: 5.2, double: 6.3, - decimal: "7.4", + decimal: 7.4, string: "Hello world!", byte: "U3dhZ2dlciByb2Nrcw==", binary: <<1, 2, 3>>, - date: "2013-10-20", - dateTime: "2013-10-20T19:20:30+01:00", + date: ~D[2013-10-20], + dateTime: ~U[2013-10-20 18:20:30Z], uuid: "3fa85f64-5717-4562-b3fc-2c963f66afa6", password: "green?horse", pattern_with_digits: "1234567890", @@ -43,7 +44,7 @@ defmodule FormatTest do end test "decode all properties (some are nil)" do - assert %FormatTest{ + assert %{ integer: nil, int32: nil, int64: nil, @@ -61,7 +62,8 @@ defmodule FormatTest do pattern_with_digits: nil, pattern_with_digits_and_delimiter: nil } - |> FormatTest.decode() == + |> then(fn params -> FormatTest.changeset(%FormatTest{}, params) end) + |> Ecto.Changeset.apply_action!(:insert) == %FormatTest{ integer: nil, int32: nil, @@ -73,7 +75,7 @@ defmodule FormatTest do string: nil, byte: "U3dhZ2dlciByb2Nrcw==", binary: nil, - date: "2013-10-20", + date: ~D[2013-10-20], dateTime: nil, uuid: nil, password: "green?horse", diff --git a/samples/client/petstore/elixir/test/mixed_properties_and_additional_properties_class_test.exs b/samples/client/petstore/elixir/test/mixed_properties_and_additional_properties_class_test.exs index 1129a221749e..375bffa54049 100644 --- a/samples/client/petstore/elixir/test/mixed_properties_and_additional_properties_class_test.exs +++ b/samples/client/petstore/elixir/test/mixed_properties_and_additional_properties_class_test.exs @@ -4,7 +4,7 @@ defmodule MixedPropertiesAndAdditionalPropertiesClass do alias OpenapiPetstore.Model.Animal test "decode all properties (not nil)" do - assert %Model{ + assert %{ uuid: "3fa85f64-5717-4562-b3fc-2c963f66afa6", dateTime: "2013-10-20T19:20:30+01:00", map: %{ @@ -12,10 +12,11 @@ defmodule MixedPropertiesAndAdditionalPropertiesClass do "meow" => %{"className" => "CAT", "color" => "white", "declawed" => false} } } - |> Model.decode() == + |> then(fn params -> Model.changeset(%Model{}, params) end) + |> Ecto.Changeset.apply_action!(:insert) == %Model{ uuid: "3fa85f64-5717-4562-b3fc-2c963f66afa6", - dateTime: "2013-10-20T19:20:30+01:00", + dateTime: ~U[2013-10-20 18:20:30Z], map: %{ # TODO values should be Dog and Cat structs instead of an Animal "doggie" => %Animal{ @@ -31,12 +32,13 @@ defmodule MixedPropertiesAndAdditionalPropertiesClass do end test "decode all properties (nil)" do - assert %Model{ + assert %{ uuid: nil, dateTime: nil, map: nil } - |> Model.decode() == + |> then(fn params -> Model.changeset(%Model{}, params) end) + |> Ecto.Changeset.apply_action!(:insert) == %Model{ uuid: nil, dateTime: nil, From 356647d3ad96ab1723fc62169af8d0ef95db3461 Mon Sep 17 00:00:00 2001 From: Enrique Fernandez Date: Tue, 6 May 2025 20:00:24 +0200 Subject: [PATCH 4/9] feat: better handling of enums --- .../languages/ElixirClientCodegen.java | 84 ++++++++++++++++++- .../src/main/resources/elixir/model.mustache | 9 +- .../model/all_of_with_single_ref.ex | 8 +- .../model/child_with_nullable.ex | 1 + .../lib/openapi_petstore/model/enum_arrays.ex | 2 + .../lib/openapi_petstore/model/enum_class.ex | 22 ----- .../lib/openapi_petstore/model/enum_test.ex | 30 ++++--- .../lib/openapi_petstore/model/map_test.ex | 1 + .../lib/openapi_petstore/model/order.ex | 1 + .../lib/openapi_petstore/model/outer_enum.ex | 22 ----- .../model/outer_enum_default_value.ex | 22 ----- .../model/outer_enum_integer.ex | 22 ----- .../model/outer_enum_integer_default_value.ex | 22 ----- .../model/outer_object_with_enum_property.ex | 10 +-- .../model/parent_with_nullable.ex | 1 + .../elixir/lib/openapi_petstore/model/pet.ex | 2 +- .../openapi_petstore/model/single_ref_type.ex | 22 ----- .../elixir/test/deserializer_test.exs | 4 +- .../petstore/elixir/test/outer_enum_test.exs | 2 + 19 files changed, 124 insertions(+), 163 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java index eb9776d4f1cb..fc0082396011 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java @@ -304,6 +304,28 @@ public void execute(Template.Fragment fragment, Writer writer) throws IOExceptio writer.write(text.toUpperCase(Locale.ROOT)); } }); + additionalProperties.put("quoteIfString", new Mustache.Lambda() { + @Override + public void execute(Template.Fragment fragment, Writer writer) throws IOException { + String text = fragment.execute(); + if (text != null) { + try { + // Try to parse as a number + Double.parseDouble(text); + // If parsing succeeds, it's a number, so write it as is + writer.write(text); + } catch (NumberFormatException e) { + // Check if it's a boolean + if (text.equals("true") || text.equals("false")) { + writer.write(text); + } else { + // It's not a number or boolean, so it's a string - quote it + writer.write("\"" + text + "\""); + } + } + } + } + }); if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) { setModuleName((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE)); @@ -426,6 +448,12 @@ public CodegenModel fromModel(String name, Schema model) { for (CodegenProperty field : requiredEctoFields) { ecm.requiredEctoFields.add(new ExtendedCodegenProperty(field)); } + + List ectoEnums = new ArrayList<>(ecm.ectoEnums); + ecm.ectoEnums.clear(); + for (CodegenProperty field : ectoEnums) { + ecm.ectoEnums.add(new ExtendedCodegenProperty(field)); + } return ecm; } @@ -910,6 +938,7 @@ class ExtendedCodegenModel extends CodegenModel { public boolean hasImports; public List ectoFields = new ArrayList<>(); public List ectoEmbeds = new ArrayList<>(); + public List ectoEnums = new ArrayList<>(); public List requiredEctoFields = new ArrayList<>(); public ExtendedCodegenModel(CodegenModel cm) { @@ -966,11 +995,14 @@ public ExtendedCodegenModel(CodegenModel cm) { this.hasImports = !this.imports.isEmpty(); for (CodegenProperty var : this.vars) { - if (var.isPrimitiveType || var.isMap) { + if (var.isPrimitiveType || var.isMap || var.isEnum || var.isEnumRef) { this.ectoFields.add(var); if (var.required) { this.requiredEctoFields.add(var); } + if (var.isEnum || var.isEnumRef) { + this.ectoEnums.add(var); + } } else { this.ectoEmbeds.add(var); } @@ -979,6 +1011,8 @@ public ExtendedCodegenModel(CodegenModel cm) { } class ExtendedCodegenProperty extends CodegenProperty { + public String enumBaseType; + public ExtendedCodegenProperty(CodegenProperty cp) { super(); @@ -1035,6 +1069,7 @@ public ExtendedCodegenProperty(CodegenProperty cp) { this.isArray = cp.isArray; this.isMap = cp.isMap; this.isEnum = cp.isEnum; + this.isEnumRef = cp.isEnumRef; this.isReadOnly = cp.isReadOnly; this.isWriteOnly = cp.isWriteOnly; this.isNullable = cp.isNullable; @@ -1045,19 +1080,62 @@ public ExtendedCodegenProperty(CodegenProperty cp) { this.vars = cp.vars; this.requiredVars = cp.requiredVars; this.vendorExtensions = cp.vendorExtensions; + + // For enum references, determine the base type from the enum values + if (cp.isEnumRef && cp.allowableValues != null && cp.allowableValues.get("values") != null) { + List values = (List) cp.allowableValues.get("values"); + if (!values.isEmpty()) { + Object firstValue = values.get(0); + if (firstValue instanceof String) { + this.enumBaseType = "String.t"; + } else if (firstValue instanceof Integer || firstValue instanceof Long) { + this.enumBaseType = "integer()"; + } else if (firstValue instanceof Float || firstValue instanceof Double) { + this.enumBaseType = "float()"; + } else if (firstValue instanceof Boolean) { + this.enumBaseType = "boolean()"; + } else { + // Default to string for unknown types + this.enumBaseType = "String.t"; + } + } else { + // No values, default to string + this.enumBaseType = "String.t"; + } + } } public String ectoType() { String ectoType = ectoType(this); - if (":any".equals(ectoType)) { return ectoType + ", virtual: true"; } - return ectoType; } private String ectoType(CodegenProperty property) { + if (property.isEnumRef) { + List values = (List) property.allowableValues.get("values"); + if (!values.isEmpty()) { + Object firstValue = values.get(0); + if (firstValue instanceof String) { + return ":string"; + } else if (firstValue instanceof Integer || firstValue instanceof Long) { + return ":integer"; + } else if (firstValue instanceof Float || firstValue instanceof Double) { + return ":float"; + } else if (firstValue instanceof Boolean) { + return ":boolean"; + } else { + // Default to string for unknown types + return ":string"; + } + } else { + // No values, default to string + return ":string"; + } + } + String baseType = property.baseType; switch (baseType) { case "integer()": diff --git a/modules/openapi-generator/src/main/resources/elixir/model.mustache b/modules/openapi-generator/src/main/resources/elixir/model.mustache index ca27997ebc14..5bfbadafc6e7 100644 --- a/modules/openapi-generator/src/main/resources/elixir/model.mustache +++ b/modules/openapi-generator/src/main/resources/elixir/model.mustache @@ -1,12 +1,12 @@ {{>licenseInfo}} -{{#models}}{{#model}}defmodule {{moduleName}}.Model.{{classname}} do +{{#models}}{{#model}}{{^isEnum}}defmodule {{moduleName}}.Model.{{classname}} do @moduledoc """ {{&description}} """ use Ecto.Schema @type t :: %__MODULE__{ - {{#vars}}{{#atom}}{{&baseName}}{{/atom}} => {{{datatype}}}{{#isNullable}} | nil{{/isNullable}}{{^isNullable}}{{^required}} | nil{{/required}}{{/isNullable}}{{^-last}}, + {{#vars}}{{#atom}}{{&baseName}}{{/atom}} => {{#isEnumRef}}{{{enumBaseType}}}{{/isEnumRef}}{{^isEnumRef}}{{{datatype}}}{{/isEnumRef}}{{#isNullable}} | nil{{/isNullable}}{{^isNullable}}{{^required}} | nil{{/required}}{{/isNullable}}{{^-last}}, {{/-last}}{{/vars}} } @@ -26,9 +26,12 @@ struct |> Ecto.Changeset.cast(params, [{{#ectoFields}}{{#atom}}{{&baseName}}{{/atom}}{{^-last}}, {{/-last}}{{/ectoFields}}]) |> Ecto.Changeset.validate_required([{{#requiredEctoFields}}{{#atom}}{{&baseName}}{{/atom}}{{^-last}}, {{/-last}}{{/requiredEctoFields}}]) + {{#ectoEnums}} + |> Ecto.Changeset.validate_inclusion({{#atom}}{{&baseName}}{{/atom}}, [{{#allowableValues}}{{#values}}{{#quoteIfString}}{{.}}{{/quoteIfString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}]) + {{/ectoEnums}} {{#ectoEmbeds}} |> Ecto.Changeset.cast_embed({{#atom}}{{&baseName}}{{/atom}}{{#required}}, required: true{{/required}}) {{/ectoEmbeds}} end end -{{/model}}{{/models}} +{{/isEnum}}{{/model}}{{/models}} diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/all_of_with_single_ref.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/all_of_with_single_ref.ex index aa6eade4786c..9205a07f061d 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/all_of_with_single_ref.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/all_of_with_single_ref.ex @@ -9,22 +9,22 @@ defmodule OpenapiPetstore.Model.AllOfWithSingleRef do @type t :: %__MODULE__{ :username => String.t | nil, - :SingleRefType => OpenapiPetstore.Model.SingleRefType.t | nil + :SingleRefType => String.t | nil } @derive {JSON.Encoder, only: [:username, :SingleRefType]} @primary_key false embedded_schema do field :username, :string - embeds_one :SingleRefType, OpenapiPetstore.Model.SingleRefType + field :SingleRefType, :string end @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct - |> Ecto.Changeset.cast(params, [:username]) + |> Ecto.Changeset.cast(params, [:username, :SingleRefType]) |> Ecto.Changeset.validate_required([]) - |> Ecto.Changeset.cast_embed(:SingleRefType) + |> Ecto.Changeset.validate_inclusion(:SingleRefType, ["admin", "user"]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/child_with_nullable.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/child_with_nullable.ex index c0e46d1f4726..1d235a362984 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/child_with_nullable.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/child_with_nullable.ex @@ -26,6 +26,7 @@ defmodule OpenapiPetstore.Model.ChildWithNullable do struct |> Ecto.Changeset.cast(params, [:type, :nullableProperty, :otherProperty]) |> Ecto.Changeset.validate_required([]) + |> Ecto.Changeset.validate_inclusion(:type, ["ChildWithNullable"]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_arrays.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_arrays.ex index 70819831c235..cd6bff9cb9a1 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_arrays.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_arrays.ex @@ -24,6 +24,8 @@ defmodule OpenapiPetstore.Model.EnumArrays do struct |> Ecto.Changeset.cast(params, [:just_symbol, :array_enum]) |> Ecto.Changeset.validate_required([]) + |> Ecto.Changeset.validate_inclusion(:just_symbol, [">=", "$"]) + |> Ecto.Changeset.validate_inclusion(:array_enum, ["fish", "crab"]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_class.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_class.ex index 5e661c1648a4..2f02be643f34 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_class.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_class.ex @@ -1,26 +1,4 @@ # NOTE: This file is auto generated by OpenAPI Generator 7.14.0-SNAPSHOT (https://openapi-generator.tech). # Do not edit this file manually. -defmodule OpenapiPetstore.Model.EnumClass do - @moduledoc """ - - """ - use Ecto.Schema - - @type t :: %__MODULE__{ - - } - - @derive {JSON.Encoder, only: []} - @primary_key false - embedded_schema do - end - - @spec changeset(t(), map()) :: Ecto.Changeset.t() - def changeset(%__MODULE__{} = struct, params) do - struct - |> Ecto.Changeset.cast(params, []) - |> Ecto.Changeset.validate_required([]) - end -end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_test.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_test.ex index 932cb367a49a..6530a327431d 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_test.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_test.ex @@ -12,10 +12,10 @@ defmodule OpenapiPetstore.Model.EnumTest do :enum_string_required => String.t, :enum_integer => integer() | nil, :enum_number => float() | nil, - :outerEnum => OpenapiPetstore.Model.OuterEnum.t | nil, - :outerEnumInteger => OpenapiPetstore.Model.OuterEnumInteger.t | nil, - :outerEnumDefaultValue => OpenapiPetstore.Model.OuterEnumDefaultValue.t | nil, - :outerEnumIntegerDefaultValue => OpenapiPetstore.Model.OuterEnumIntegerDefaultValue.t | nil + :outerEnum => String.t | nil, + :outerEnumInteger => integer() | nil, + :outerEnumDefaultValue => String.t | nil, + :outerEnumIntegerDefaultValue => integer() | nil } @derive {JSON.Encoder, only: [:enum_string, :enum_string_required, :enum_integer, :enum_number, :outerEnum, :outerEnumInteger, :outerEnumDefaultValue, :outerEnumIntegerDefaultValue]} @@ -25,21 +25,25 @@ defmodule OpenapiPetstore.Model.EnumTest do field :enum_string_required, :string field :enum_integer, :integer field :enum_number, :float - embeds_one :outerEnum, OpenapiPetstore.Model.OuterEnum - embeds_one :outerEnumInteger, OpenapiPetstore.Model.OuterEnumInteger - embeds_one :outerEnumDefaultValue, OpenapiPetstore.Model.OuterEnumDefaultValue - embeds_one :outerEnumIntegerDefaultValue, OpenapiPetstore.Model.OuterEnumIntegerDefaultValue + field :outerEnum, :string + field :outerEnumInteger, :integer + field :outerEnumDefaultValue, :string + field :outerEnumIntegerDefaultValue, :integer end @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct - |> Ecto.Changeset.cast(params, [:enum_string, :enum_string_required, :enum_integer, :enum_number]) + |> Ecto.Changeset.cast(params, [:enum_string, :enum_string_required, :enum_integer, :enum_number, :outerEnum, :outerEnumInteger, :outerEnumDefaultValue, :outerEnumIntegerDefaultValue]) |> Ecto.Changeset.validate_required([:enum_string_required]) - |> Ecto.Changeset.cast_embed(:outerEnum) - |> Ecto.Changeset.cast_embed(:outerEnumInteger) - |> Ecto.Changeset.cast_embed(:outerEnumDefaultValue) - |> Ecto.Changeset.cast_embed(:outerEnumIntegerDefaultValue) + |> Ecto.Changeset.validate_inclusion(:enum_string, ["UPPER", "lower", ""]) + |> Ecto.Changeset.validate_inclusion(:enum_string_required, ["UPPER", "lower", ""]) + |> Ecto.Changeset.validate_inclusion(:enum_integer, [1, -1]) + |> Ecto.Changeset.validate_inclusion(:enum_number, [1.1, -1.2]) + |> Ecto.Changeset.validate_inclusion(:outerEnum, ["placed", "approved", "delivered"]) + |> Ecto.Changeset.validate_inclusion(:outerEnumInteger, [0, 1, 2]) + |> Ecto.Changeset.validate_inclusion(:outerEnumDefaultValue, ["placed", "approved", "delivered"]) + |> Ecto.Changeset.validate_inclusion(:outerEnumIntegerDefaultValue, [0, 1, 2]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex index 9ea5e2a4583a..0bf818f6dd4f 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex @@ -28,6 +28,7 @@ defmodule OpenapiPetstore.Model.MapTest do struct |> Ecto.Changeset.cast(params, [:map_map_of_string, :map_of_enum_string, :direct_map, :indirect_map]) |> Ecto.Changeset.validate_required([]) + |> Ecto.Changeset.validate_inclusion(:map_of_enum_string, ["UPPER", "lower"]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/order.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/order.ex index 491c498f7149..7a98cd862225 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/order.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/order.ex @@ -32,6 +32,7 @@ defmodule OpenapiPetstore.Model.Order do struct |> Ecto.Changeset.cast(params, [:id, :petId, :quantity, :shipDate, :status, :complete]) |> Ecto.Changeset.validate_required([]) + |> Ecto.Changeset.validate_inclusion(:status, ["placed", "approved", "delivered"]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum.ex index 4b878199f396..2f02be643f34 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum.ex @@ -1,26 +1,4 @@ # NOTE: This file is auto generated by OpenAPI Generator 7.14.0-SNAPSHOT (https://openapi-generator.tech). # Do not edit this file manually. -defmodule OpenapiPetstore.Model.OuterEnum do - @moduledoc """ - - """ - use Ecto.Schema - - @type t :: %__MODULE__{ - - } - - @derive {JSON.Encoder, only: []} - @primary_key false - embedded_schema do - end - - @spec changeset(t(), map()) :: Ecto.Changeset.t() - def changeset(%__MODULE__{} = struct, params) do - struct - |> Ecto.Changeset.cast(params, []) - |> Ecto.Changeset.validate_required([]) - end -end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_default_value.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_default_value.ex index 818f8b77b0a2..2f02be643f34 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_default_value.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_default_value.ex @@ -1,26 +1,4 @@ # NOTE: This file is auto generated by OpenAPI Generator 7.14.0-SNAPSHOT (https://openapi-generator.tech). # Do not edit this file manually. -defmodule OpenapiPetstore.Model.OuterEnumDefaultValue do - @moduledoc """ - - """ - use Ecto.Schema - - @type t :: %__MODULE__{ - - } - - @derive {JSON.Encoder, only: []} - @primary_key false - embedded_schema do - end - - @spec changeset(t(), map()) :: Ecto.Changeset.t() - def changeset(%__MODULE__{} = struct, params) do - struct - |> Ecto.Changeset.cast(params, []) - |> Ecto.Changeset.validate_required([]) - end -end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer.ex index c06d74991b82..2f02be643f34 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer.ex @@ -1,26 +1,4 @@ # NOTE: This file is auto generated by OpenAPI Generator 7.14.0-SNAPSHOT (https://openapi-generator.tech). # Do not edit this file manually. -defmodule OpenapiPetstore.Model.OuterEnumInteger do - @moduledoc """ - - """ - use Ecto.Schema - - @type t :: %__MODULE__{ - - } - - @derive {JSON.Encoder, only: []} - @primary_key false - embedded_schema do - end - - @spec changeset(t(), map()) :: Ecto.Changeset.t() - def changeset(%__MODULE__{} = struct, params) do - struct - |> Ecto.Changeset.cast(params, []) - |> Ecto.Changeset.validate_required([]) - end -end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer_default_value.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer_default_value.ex index 19767ff3fd32..2f02be643f34 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer_default_value.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_enum_integer_default_value.ex @@ -1,26 +1,4 @@ # NOTE: This file is auto generated by OpenAPI Generator 7.14.0-SNAPSHOT (https://openapi-generator.tech). # Do not edit this file manually. -defmodule OpenapiPetstore.Model.OuterEnumIntegerDefaultValue do - @moduledoc """ - - """ - use Ecto.Schema - - @type t :: %__MODULE__{ - - } - - @derive {JSON.Encoder, only: []} - @primary_key false - embedded_schema do - end - - @spec changeset(t(), map()) :: Ecto.Changeset.t() - def changeset(%__MODULE__{} = struct, params) do - struct - |> Ecto.Changeset.cast(params, []) - |> Ecto.Changeset.validate_required([]) - end -end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_object_with_enum_property.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_object_with_enum_property.ex index 2bca96bea61b..b21221392dd1 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_object_with_enum_property.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_object_with_enum_property.ex @@ -8,21 +8,21 @@ defmodule OpenapiPetstore.Model.OuterObjectWithEnumProperty do use Ecto.Schema @type t :: %__MODULE__{ - :value => OpenapiPetstore.Model.OuterEnumInteger.t + :value => integer() } @derive {JSON.Encoder, only: [:value]} @primary_key false embedded_schema do - embeds_one :value, OpenapiPetstore.Model.OuterEnumInteger + field :value, :integer end @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct - |> Ecto.Changeset.cast(params, []) - |> Ecto.Changeset.validate_required([]) - |> Ecto.Changeset.cast_embed(:value, required: true) + |> Ecto.Changeset.cast(params, [:value]) + |> Ecto.Changeset.validate_required([:value]) + |> Ecto.Changeset.validate_inclusion(:value, [0, 1, 2]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/parent_with_nullable.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/parent_with_nullable.ex index 6a726f09d846..3ee8f8a7b7a9 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/parent_with_nullable.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/parent_with_nullable.ex @@ -24,6 +24,7 @@ defmodule OpenapiPetstore.Model.ParentWithNullable do struct |> Ecto.Changeset.cast(params, [:type, :nullableProperty]) |> Ecto.Changeset.validate_required([]) + |> Ecto.Changeset.validate_inclusion(:type, ["ChildWithNullable"]) end end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex index 219c72718582..361760fe0d71 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex @@ -22,7 +22,6 @@ defmodule OpenapiPetstore.Model.Pet do field :id, :integer field :name, :string field :photoUrls, {:array, :string} - embeds_many :tags, OpenapiPetstore.Model.Tag field :status, :string embeds_one :category, OpenapiPetstore.Model.Category embeds_many :tags, OpenapiPetstore.Model.Tag @@ -33,6 +32,7 @@ defmodule OpenapiPetstore.Model.Pet do struct |> Ecto.Changeset.cast(params, [:id, :name, :photoUrls, :status]) |> Ecto.Changeset.validate_required([:name, :photoUrls]) + |> Ecto.Changeset.validate_inclusion(:status, ["available", "pending", "sold"]) |> Ecto.Changeset.cast_embed(:category) |> Ecto.Changeset.cast_embed(:tags) end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/single_ref_type.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/single_ref_type.ex index f5bc6cc7575a..2f02be643f34 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/single_ref_type.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/single_ref_type.ex @@ -1,26 +1,4 @@ # NOTE: This file is auto generated by OpenAPI Generator 7.14.0-SNAPSHOT (https://openapi-generator.tech). # Do not edit this file manually. -defmodule OpenapiPetstore.Model.SingleRefType do - @moduledoc """ - - """ - use Ecto.Schema - - @type t :: %__MODULE__{ - - } - - @derive {JSON.Encoder, only: []} - @primary_key false - embedded_schema do - end - - @spec changeset(t(), map()) :: Ecto.Changeset.t() - def changeset(%__MODULE__{} = struct, params) do - struct - |> Ecto.Changeset.cast(params, []) - |> Ecto.Changeset.validate_required([]) - end -end diff --git a/samples/client/petstore/elixir/test/deserializer_test.exs b/samples/client/petstore/elixir/test/deserializer_test.exs index 41498e64ac1d..aac7a6822e09 100644 --- a/samples/client/petstore/elixir/test/deserializer_test.exs +++ b/samples/client/petstore/elixir/test/deserializer_test.exs @@ -24,7 +24,7 @@ defmodule DeserializerTest do "name": "sea" } ], - "status": "foo" + "status": "available" } """ @@ -41,7 +41,7 @@ defmodule DeserializerTest do name: "Nagga", photoUrls: ["https://example.com/nagga1.jpg", "https://example.com/nagga2.jpg"], tags: [%Tag{id: 99, name: "dragon"}, %Tag{id: 23, name: "sea"}], - status: "foo" + status: "available" } end diff --git a/samples/client/petstore/elixir/test/outer_enum_test.exs b/samples/client/petstore/elixir/test/outer_enum_test.exs index 57dc65974ea9..c865e2d2d46c 100644 --- a/samples/client/petstore/elixir/test/outer_enum_test.exs +++ b/samples/client/petstore/elixir/test/outer_enum_test.exs @@ -5,6 +5,7 @@ defmodule OuterEnumTest do @valid_json """ { + "enum_string_required": "lower", "enum_string": "UPPER", "enum_number": 1.1, "outerEnum": "placed", @@ -21,6 +22,7 @@ defmodule OuterEnumTest do assert enum_test == %EnumTest{ + enum_string_required: "lower", enum_string: "UPPER", enum_number: 1.1, outerEnum: "placed", From 93a33350c7225ba71f7a7fa435367d43ccf8dccd Mon Sep 17 00:00:00 2001 From: Enrique Fernandez Date: Thu, 8 May 2025 19:04:55 +0200 Subject: [PATCH 5/9] fix: inner types in maps --- .../codegen/languages/ElixirClientCodegen.java | 6 +++++- .../model/additional_properties_class.ex | 4 ++-- .../model/fake_big_decimal_map_200_response.ex | 2 +- .../elixir/lib/openapi_petstore/model/map_test.ex | 8 ++++---- ...xed_properties_and_additional_properties_class.ex | 2 +- .../lib/openapi_petstore/model/nullable_class.ex | 12 ++++++------ 6 files changed, 19 insertions(+), 15 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java index fc0082396011..73672984027f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java @@ -1114,6 +1114,10 @@ public String ectoType() { } private String ectoType(CodegenProperty property) { + if (property == null) { + return ":any"; + } + if (property.isEnumRef) { List values = (List) property.allowableValues.get("values"); if (!values.isEmpty()) { @@ -1157,7 +1161,7 @@ private String ectoType(CodegenProperty property) { case "list()": return "{:array, " + ectoType(property.items) + "}"; case "map()": - return ":map"; + return "{:map, " + ectoType(property.items) + "}"; case "nil": return ":any"; default: diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/additional_properties_class.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/additional_properties_class.ex index 5ffc92bee1cf..0c27d403f160 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/additional_properties_class.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/additional_properties_class.ex @@ -15,8 +15,8 @@ defmodule OpenapiPetstore.Model.AdditionalPropertiesClass do @derive {JSON.Encoder, only: [:map_property, :map_of_map_property]} @primary_key false embedded_schema do - field :map_property, :map - field :map_of_map_property, :map + field :map_property, {:map, :string} + field :map_of_map_property, {:map, {:map, :string}} end @spec changeset(t(), map()) :: Ecto.Changeset.t() diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/fake_big_decimal_map_200_response.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/fake_big_decimal_map_200_response.ex index 75602eeec9ed..7be5755e8830 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/fake_big_decimal_map_200_response.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/fake_big_decimal_map_200_response.ex @@ -16,7 +16,7 @@ defmodule OpenapiPetstore.Model.FakeBigDecimalMap200Response do @primary_key false embedded_schema do field :someId, :float - field :someMap, :map + field :someMap, {:map, :float} end @spec changeset(t(), map()) :: Ecto.Changeset.t() diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex index 0bf818f6dd4f..6f43902cc954 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex @@ -17,10 +17,10 @@ defmodule OpenapiPetstore.Model.MapTest do @derive {JSON.Encoder, only: [:map_map_of_string, :map_of_enum_string, :direct_map, :indirect_map]} @primary_key false embedded_schema do - field :map_map_of_string, :map - field :map_of_enum_string, :map - field :direct_map, :map - field :indirect_map, :map + field :map_map_of_string, {:map, {:map, :string}} + field :map_of_enum_string, {:map, :string} + field :direct_map, {:map, :boolean} + field :indirect_map, {:map, :boolean} end @spec changeset(t(), map()) :: Ecto.Changeset.t() diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex index e8d3561adfe8..5779eb3fec57 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex @@ -18,7 +18,7 @@ defmodule OpenapiPetstore.Model.MixedPropertiesAndAdditionalPropertiesClass do embedded_schema do field :uuid, :string field :dateTime, :utc_datetime - field :map, :map + field :map, {:map, :any} end @spec changeset(t(), map()) :: Ecto.Changeset.t() diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/nullable_class.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/nullable_class.ex index 905700b798bc..f10b31fb43b6 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/nullable_class.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/nullable_class.ex @@ -31,12 +31,12 @@ defmodule OpenapiPetstore.Model.NullableClass do field :string_prop, :string field :date_prop, :date field :datetime_prop, :utc_datetime - field :array_nullable_prop, {:array, :map} - field :array_and_items_nullable_prop, {:array, :map} - field :array_items_nullable, {:array, :map} - field :object_nullable_prop, :map - field :object_and_items_nullable_prop, :map - field :object_items_nullable, :map + field :array_nullable_prop, {:array, {:map, :any}} + field :array_and_items_nullable_prop, {:array, {:map, :any}} + field :array_items_nullable, {:array, {:map, :any}} + field :object_nullable_prop, {:map, {:map, :any}} + field :object_and_items_nullable_prop, {:map, {:map, :any}} + field :object_items_nullable, {:map, {:map, :any}} end @spec changeset(t(), map()) :: Ecto.Changeset.t() From 539259501fffc681a476a88c3c464ce876771c76 Mon Sep 17 00:00:00 2001 From: Enrique Fernandez Date: Thu, 8 May 2025 17:00:00 +0200 Subject: [PATCH 6/9] feat: maps with nested models --- .../languages/ElixirClientCodegen.java | 28 +++++++++++++++ .../resources/elixir/ecto_utils.ex.mustache | 33 +++++++++++++++++ .../src/main/resources/elixir/model.mustache | 3 ++ .../petstore/elixir/.openapi-generator/FILES | 1 + .../elixir/lib/openapi_petstore/ecto_utils.ex | 35 +++++++++++++++++++ ...perties_and_additional_properties_class.ex | 1 + 6 files changed, 101 insertions(+) create mode 100644 modules/openapi-generator/src/main/resources/elixir/ecto_utils.ex.mustache create mode 100644 samples/client/petstore/elixir/lib/openapi_petstore/ecto_utils.ex diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java index 73672984027f..aec01e015e84 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java @@ -360,6 +360,10 @@ public void preprocessOpenAPI(OpenAPI openAPI) { supportingFiles.add(new SupportingFile("request_builder.ex.mustache", sourceFolder(), "request_builder.ex")); + + supportingFiles.add(new SupportingFile("ecto_utils.ex.mustache", + sourceFolder(), + "ecto_utils.ex")); } @Override @@ -454,6 +458,13 @@ public CodegenModel fromModel(String name, Schema model) { for (CodegenProperty field : ectoEnums) { ecm.ectoEnums.add(new ExtendedCodegenProperty(field)); } + + + List ectoMaps = new ArrayList<>(ecm.ectoMaps); + ecm.ectoMaps.clear(); + for (CodegenProperty field : ectoMaps) { + ecm.ectoMaps.add(new ExtendedCodegenProperty(field)); + } return ecm; } @@ -939,6 +950,7 @@ class ExtendedCodegenModel extends CodegenModel { public List ectoFields = new ArrayList<>(); public List ectoEmbeds = new ArrayList<>(); public List ectoEnums = new ArrayList<>(); + public List ectoMaps = new ArrayList<>(); public List requiredEctoFields = new ArrayList<>(); public ExtendedCodegenModel(CodegenModel cm) { @@ -1003,6 +1015,9 @@ public ExtendedCodegenModel(CodegenModel cm) { if (var.isEnum || var.isEnumRef) { this.ectoEnums.add(var); } + if (var.isMap && !var.isFreeFormObject && var.additionalProperties != null && var.additionalProperties.isModel) { + this.ectoMaps.add(var); + } } else { this.ectoEmbeds.add(var); } @@ -1012,6 +1027,8 @@ public ExtendedCodegenModel(CodegenModel cm) { class ExtendedCodegenProperty extends CodegenProperty { public String enumBaseType; + public String mapValueType; + public boolean isMapWithSchema; public ExtendedCodegenProperty(CodegenProperty cp) { super(); @@ -1103,6 +1120,17 @@ public ExtendedCodegenProperty(CodegenProperty cp) { this.enumBaseType = "String.t"; } } + // For map properties, extract the model name from additionalProperties + if (cp.isMap && cp.additionalProperties != null) { + // Check if the map has a schema (model) or is a free-form map + if (cp.additionalProperties.isModel) { + // Extract just the model name without the full type declaration + this.mapValueType = cp.additionalProperties.complexType; + this.isMapWithSchema = true; + } else { + this.isMapWithSchema = false; + } + } } public String ectoType() { diff --git a/modules/openapi-generator/src/main/resources/elixir/ecto_utils.ex.mustache b/modules/openapi-generator/src/main/resources/elixir/ecto_utils.ex.mustache new file mode 100644 index 000000000000..91fa0d092dbc --- /dev/null +++ b/modules/openapi-generator/src/main/resources/elixir/ecto_utils.ex.mustache @@ -0,0 +1,33 @@ +{{>licenseInfo}} +defmodule {{moduleName}}.EctoUtils do + def cast_nested_map(changeset, field, schema) do + case Map.get(changeset.changes, field) do + nil -> + changeset + + values -> + {result_map, errors} = + Enum.reduce(values, {%{}, []}, fn {key, params}, {acc, errs} -> + changeset = schema.changeset(struct(schema), params) + + case Ecto.Changeset.apply_action(changeset, changeset.action || :insert) do + {:ok, struct} -> + {Map.put(acc, key, struct), errs} + + {:error, nested_cs} -> + {Map.put(acc, key, nested_cs), [{key, nested_cs} | errs]} + end + end) + + changeset = + Ecto.Changeset.put_change(changeset, field, result_map) + + if errors == [] do + changeset + else + Ecto.Changeset.add_error(changeset, field, "contains invalid nested entries") + |> Map.put(:valid?, false) + end + end + end +end diff --git a/modules/openapi-generator/src/main/resources/elixir/model.mustache b/modules/openapi-generator/src/main/resources/elixir/model.mustache index 5bfbadafc6e7..ae293fbdf44c 100644 --- a/modules/openapi-generator/src/main/resources/elixir/model.mustache +++ b/modules/openapi-generator/src/main/resources/elixir/model.mustache @@ -29,6 +29,9 @@ {{#ectoEnums}} |> Ecto.Changeset.validate_inclusion({{#atom}}{{&baseName}}{{/atom}}, [{{#allowableValues}}{{#values}}{{#quoteIfString}}{{.}}{{/quoteIfString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}]) {{/ectoEnums}} + {{#ectoMaps}} + |> {{moduleName}}.EctoUtils.cast_nested_map({{#atom}}{{&baseName}}{{/atom}}, {{&moduleName}}.Model.{{{mapValueType}}}) + {{/ectoMaps}} {{#ectoEmbeds}} |> Ecto.Changeset.cast_embed({{#atom}}{{&baseName}}{{/atom}}{{#required}}, required: true{{/required}}) {{/ectoEmbeds}} diff --git a/samples/client/petstore/elixir/.openapi-generator/FILES b/samples/client/petstore/elixir/.openapi-generator/FILES index 7aeefea2dfb2..c7932e54f3d9 100644 --- a/samples/client/petstore/elixir/.openapi-generator/FILES +++ b/samples/client/petstore/elixir/.openapi-generator/FILES @@ -11,6 +11,7 @@ lib/openapi_petstore/api/pet.ex lib/openapi_petstore/api/store.ex lib/openapi_petstore/api/user.ex lib/openapi_petstore/connection.ex +lib/openapi_petstore/ecto_utils.ex lib/openapi_petstore/model/_foo_get_default_response.ex lib/openapi_petstore/model/_special_model_name_.ex lib/openapi_petstore/model/additional_properties_class.ex diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/ecto_utils.ex b/samples/client/petstore/elixir/lib/openapi_petstore/ecto_utils.ex new file mode 100644 index 000000000000..38747709eeaa --- /dev/null +++ b/samples/client/petstore/elixir/lib/openapi_petstore/ecto_utils.ex @@ -0,0 +1,35 @@ +# NOTE: This file is auto generated by OpenAPI Generator 7.14.0-SNAPSHOT (https://openapi-generator.tech). +# Do not edit this file manually. + +defmodule OpenapiPetstore.EctoUtils do + def cast_nested_map(changeset, field, schema) do + case Map.get(changeset.changes, field) do + nil -> + changeset + + values -> + {result_map, errors} = + Enum.reduce(values, {%{}, []}, fn {key, params}, {acc, errs} -> + changeset = schema.changeset(struct(schema), params) + + case Ecto.Changeset.apply_action(changeset, changeset.action || :insert) do + {:ok, struct} -> + {Map.put(acc, key, struct), errs} + + {:error, nested_cs} -> + {Map.put(acc, key, nested_cs), [{key, nested_cs} | errs]} + end + end) + + changeset = + Ecto.Changeset.put_change(changeset, field, result_map) + + if errors == [] do + changeset + else + Ecto.Changeset.add_error(changeset, field, "contains invalid nested entries") + |> Map.put(:valid?, false) + end + end + end +end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex index 5779eb3fec57..d4f903dd6952 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex @@ -26,6 +26,7 @@ defmodule OpenapiPetstore.Model.MixedPropertiesAndAdditionalPropertiesClass do struct |> Ecto.Changeset.cast(params, [:uuid, :dateTime, :map]) |> Ecto.Changeset.validate_required([]) + |> OpenapiPetstore.EctoUtils.cast_nested_map(:map, OpenapiPetstore.Model.Animal) end end From 6ad3d7857af912700bc5d1382cf4dea854521908 Mon Sep 17 00:00:00 2001 From: Enrique Fernandez Date: Thu, 8 May 2025 19:42:13 +0200 Subject: [PATCH 7/9] fix: implicit json decoding --- .../resources/elixir/connection.ex.mustache | 2 +- .../elixir/request_builder.ex.mustache | 26 +++++++++---------- .../elixir/lib/openapi_petstore/connection.ex | 2 +- .../lib/openapi_petstore/request_builder.ex | 26 +++++++++---------- 4 files changed, 26 insertions(+), 30 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/elixir/connection.ex.mustache b/modules/openapi-generator/src/main/resources/elixir/connection.ex.mustache index 3622d62437c4..dc05706afd8b 100644 --- a/modules/openapi-generator/src/main/resources/elixir/connection.ex.mustache +++ b/modules/openapi-generator/src/main/resources/elixir/connection.ex.mustache @@ -150,7 +150,7 @@ defmodule {{moduleName}}.Connection do [ {Tesla.Middleware.BaseUrl, base_url}, {Tesla.Middleware.Headers, [{"user-agent", user_agent}]}, - {Tesla.Middleware.EncodeJson, engine: json_engine} + {Tesla.Middleware.JSON, engine: json_engine} | middleware ] end diff --git a/modules/openapi-generator/src/main/resources/elixir/request_builder.ex.mustache b/modules/openapi-generator/src/main/resources/elixir/request_builder.ex.mustache index e89e548a67df..6d5ee9b06b9c 100644 --- a/modules/openapi-generator/src/main/resources/elixir/request_builder.ex.mustache +++ b/modules/openapi-generator/src/main/resources/elixir/request_builder.ex.mustache @@ -187,20 +187,18 @@ defmodule {{moduleName}}.RequestBuilder do defp decode(%Tesla.Env{} = env, false), do: {:ok, env} defp decode(%Tesla.Env{body: body}, %{}) do - JSON.decode(body) - end - - defp decode(%Tesla.Env{body: body}, module) do - case JSON.decode(body) do - {:ok, objects} when is_list(objects) -> - models = Enum.map(objects, fn object -> - {:ok, model} = to_model(module, object) - model - end) - {:ok, models} - {:ok, params} -> to_model(module, params) - {:error, error} -> {:error, error} - end + {:ok, body} + end + + defp decode(%Tesla.Env{body: response}, module) when is_list(response) do + models = Enum.map(response, fn params -> + {:ok, model} = to_model(module, params) + model + end) + {:ok, models} + end + defp decode(%Tesla.Env{body: params}, module) do + to_model(module, params) end defp to_model(module, params) do diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/connection.ex b/samples/client/petstore/elixir/lib/openapi_petstore/connection.ex index fed0639550d2..1766b33b113c 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/connection.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/connection.ex @@ -130,7 +130,7 @@ defmodule OpenapiPetstore.Connection do [ {Tesla.Middleware.BaseUrl, base_url}, {Tesla.Middleware.Headers, [{"user-agent", user_agent}]}, - {Tesla.Middleware.EncodeJson, engine: json_engine} + {Tesla.Middleware.JSON, engine: json_engine} | middleware ] end diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/request_builder.ex b/samples/client/petstore/elixir/lib/openapi_petstore/request_builder.ex index 7e62461435ee..ef598dd50a8b 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/request_builder.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/request_builder.ex @@ -189,20 +189,18 @@ defmodule OpenapiPetstore.RequestBuilder do defp decode(%Tesla.Env{} = env, false), do: {:ok, env} defp decode(%Tesla.Env{body: body}, %{}) do - JSON.decode(body) - end - - defp decode(%Tesla.Env{body: body}, module) do - case JSON.decode(body) do - {:ok, objects} when is_list(objects) -> - models = Enum.map(objects, fn object -> - {:ok, model} = to_model(module, object) - model - end) - {:ok, models} - {:ok, params} -> to_model(module, params) - {:error, error} -> {:error, error} - end + {:ok, body} + end + + defp decode(%Tesla.Env{body: response}, module) when is_list(response) do + models = Enum.map(response, fn params -> + {:ok, model} = to_model(module, params) + model + end) + {:ok, models} + end + defp decode(%Tesla.Env{body: params}, module) do + to_model(module, params) end defp to_model(module, params) do From 231bd3dce175ea53a0449d1d12d182781643a4cb Mon Sep 17 00:00:00 2001 From: Enrique Fernandez Date: Tue, 13 May 2025 10:32:59 +0200 Subject: [PATCH 8/9] feat: use ecto's formatter --- .../openapi-generator/src/main/resources/elixir/formatter.exs | 1 + samples/client/petstore/elixir/.formatter.exs | 1 + 2 files changed, 2 insertions(+) diff --git a/modules/openapi-generator/src/main/resources/elixir/formatter.exs b/modules/openapi-generator/src/main/resources/elixir/formatter.exs index d304ff320a52..a79525b1a195 100644 --- a/modules/openapi-generator/src/main/resources/elixir/formatter.exs +++ b/modules/openapi-generator/src/main/resources/elixir/formatter.exs @@ -1,3 +1,4 @@ [ + import_deps: [:ecto], inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] ] diff --git a/samples/client/petstore/elixir/.formatter.exs b/samples/client/petstore/elixir/.formatter.exs index d304ff320a52..a79525b1a195 100644 --- a/samples/client/petstore/elixir/.formatter.exs +++ b/samples/client/petstore/elixir/.formatter.exs @@ -1,3 +1,4 @@ [ + import_deps: [:ecto], inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] ] From 3f6e3f3b9f534a29f0119b9b925f3a9db833d72c Mon Sep 17 00:00:00 2001 From: Enrique Fernandez Date: Tue, 13 May 2025 10:52:16 +0200 Subject: [PATCH 9/9] feat: from_params/1 function --- .../src/main/resources/elixir/model.mustache | 7 + .../model/_foo_get_default_response.ex | 7 + .../model/_special_model_name_.ex | 7 + .../model/additional_properties_class.ex | 7 + .../model/all_of_with_single_ref.ex | 7 + .../lib/openapi_petstore/model/animal.ex | 7 + .../elixir/lib/openapi_petstore/model/any.ex | 7 + .../openapi_petstore/model/api_response.ex | 7 + .../model/array_of_array_of_number_only.ex | 7 + .../model/array_of_number_only.ex | 7 + .../lib/openapi_petstore/model/array_test.ex | 7 + .../openapi_petstore/model/capitalization.ex | 7 + .../elixir/lib/openapi_petstore/model/cat.ex | 7 + .../lib/openapi_petstore/model/category.ex | 7 + .../model/child_with_nullable.ex | 7 + .../lib/openapi_petstore/model/class_model.ex | 7 + .../lib/openapi_petstore/model/client.ex | 7 + .../model/deprecated_model.ex | 7 + .../elixir/lib/openapi_petstore/model/dog.ex | 7 + .../lib/openapi_petstore/model/enum_arrays.ex | 7 + .../lib/openapi_petstore/model/enum_test.ex | 7 + .../fake_big_decimal_map_200_response.ex | 7 + .../elixir/lib/openapi_petstore/model/file.ex | 7 + .../model/file_schema_test_class.ex | 7 + .../elixir/lib/openapi_petstore/model/foo.ex | 7 + .../lib/openapi_petstore/model/format_test.ex | 7 + .../model/has_only_read_only.ex | 7 + .../model/health_check_result.ex | 7 + .../elixir/lib/openapi_petstore/model/list.ex | 7 + .../lib/openapi_petstore/model/map_test.ex | 7 + ...perties_and_additional_properties_class.ex | 7 + .../model/model_200_response.ex | 7 + .../elixir/lib/openapi_petstore/model/name.ex | 7 + .../openapi_petstore/model/nullable_class.ex | 7 + .../lib/openapi_petstore/model/number_only.ex | 7 + .../model/object_with_deprecated_fields.ex | 7 + .../lib/openapi_petstore/model/order.ex | 7 + .../openapi_petstore/model/outer_composite.ex | 7 + .../model/outer_object_with_enum_property.ex | 7 + .../model/parent_with_nullable.ex | 7 + .../elixir/lib/openapi_petstore/model/pet.ex | 7 + .../openapi_petstore/model/read_only_first.ex | 7 + .../lib/openapi_petstore/model/return.ex | 7 + .../elixir/lib/openapi_petstore/model/tag.ex | 7 + ..._freeform_additional_properties_request.ex | 7 + .../elixir/lib/openapi_petstore/model/user.ex | 7 + .../client/petstore/elixir/test/any_test.exs | 18 +- .../elixir/test/deserializer_test.exs | 5 +- .../petstore/elixir/test/format_test.exs | 156 +++++++++--------- ...s_and_additional_properties_class_test.exs | 78 ++++----- .../petstore/elixir/test/outer_enum_test.exs | 5 +- 51 files changed, 457 insertions(+), 127 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/elixir/model.mustache b/modules/openapi-generator/src/main/resources/elixir/model.mustache index ae293fbdf44c..8cbc11c352d1 100644 --- a/modules/openapi-generator/src/main/resources/elixir/model.mustache +++ b/modules/openapi-generator/src/main/resources/elixir/model.mustache @@ -21,6 +21,13 @@ {{/ectoEmbeds}} end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/_foo_get_default_response.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/_foo_get_default_response.ex index 68c60d6b2140..4c9d4e89fc17 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/_foo_get_default_response.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/_foo_get_default_response.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.FooGetDefaultResponse do embeds_one :string, OpenapiPetstore.Model.Foo end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/_special_model_name_.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/_special_model_name_.ex index 642505d60d9c..c3a07ed96f18 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/_special_model_name_.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/_special_model_name_.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.SpecialModelName do field :"$special[property.name]", :integer end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/additional_properties_class.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/additional_properties_class.ex index 0c27d403f160..ba61072ed1d1 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/additional_properties_class.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/additional_properties_class.ex @@ -19,6 +19,13 @@ defmodule OpenapiPetstore.Model.AdditionalPropertiesClass do field :map_of_map_property, {:map, {:map, :string}} end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/all_of_with_single_ref.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/all_of_with_single_ref.ex index 9205a07f061d..d20e7e2c9c68 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/all_of_with_single_ref.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/all_of_with_single_ref.ex @@ -19,6 +19,13 @@ defmodule OpenapiPetstore.Model.AllOfWithSingleRef do field :SingleRefType, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/animal.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/animal.ex index 872257588005..33b4fd0e27a7 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/animal.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/animal.ex @@ -19,6 +19,13 @@ defmodule OpenapiPetstore.Model.Animal do field :color, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/any.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/any.ex index 0cad3c311356..9408018344ac 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/any.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/any.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.Any do field :"@type", :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/api_response.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/api_response.ex index 4054e9e4c699..ffaec85cd232 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/api_response.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/api_response.ex @@ -21,6 +21,13 @@ defmodule OpenapiPetstore.Model.ApiResponse do field :message, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_array_of_number_only.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_array_of_number_only.ex index 944fcc5be0e9..9d0a4d80796a 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_array_of_number_only.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_array_of_number_only.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.ArrayOfArrayOfNumberOnly do field :ArrayArrayNumber, {:array, {:array, :float}} end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_number_only.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_number_only.ex index 8fafd9c29842..5326e227d8ce 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_number_only.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_number_only.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.ArrayOfNumberOnly do field :ArrayNumber, {:array, :float} end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/array_test.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/array_test.ex index 1fd276fa8b68..62486bf28dd4 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/array_test.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/array_test.ex @@ -21,6 +21,13 @@ defmodule OpenapiPetstore.Model.ArrayTest do field :array_array_of_model, {:array, {:array, :any}} end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/capitalization.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/capitalization.ex index 5169515612c6..57c95d4e2483 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/capitalization.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/capitalization.ex @@ -27,6 +27,13 @@ defmodule OpenapiPetstore.Model.Capitalization do field :ATT_NAME, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/cat.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/cat.ex index fb593c520df6..2b3958907ea3 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/cat.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/cat.ex @@ -21,6 +21,13 @@ defmodule OpenapiPetstore.Model.Cat do field :declawed, :boolean end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/category.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/category.ex index 42efd3cc7d5b..f707f40be5a7 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/category.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/category.ex @@ -19,6 +19,13 @@ defmodule OpenapiPetstore.Model.Category do field :name, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/child_with_nullable.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/child_with_nullable.ex index 1d235a362984..240edd0247a9 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/child_with_nullable.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/child_with_nullable.ex @@ -21,6 +21,13 @@ defmodule OpenapiPetstore.Model.ChildWithNullable do field :otherProperty, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/class_model.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/class_model.ex index 6e37614a15d6..2fcfe4a21a66 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/class_model.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/class_model.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.ClassModel do field :_class, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/client.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/client.ex index 262f88713b7c..301c7e1f7828 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/client.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/client.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.Client do field :client, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/deprecated_model.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/deprecated_model.ex index ac45e9aed5e7..3b53a5ffed19 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/deprecated_model.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/deprecated_model.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.DeprecatedModel do field :name, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/dog.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/dog.ex index 79e2b8c12931..45b78ec36d5e 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/dog.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/dog.ex @@ -21,6 +21,13 @@ defmodule OpenapiPetstore.Model.Dog do field :breed, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_arrays.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_arrays.ex index cd6bff9cb9a1..6a13420d376c 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_arrays.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_arrays.ex @@ -19,6 +19,13 @@ defmodule OpenapiPetstore.Model.EnumArrays do field :array_enum, {:array, :string} end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_test.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_test.ex index 6530a327431d..a0db0d8969a1 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_test.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/enum_test.ex @@ -31,6 +31,13 @@ defmodule OpenapiPetstore.Model.EnumTest do field :outerEnumIntegerDefaultValue, :integer end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/fake_big_decimal_map_200_response.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/fake_big_decimal_map_200_response.ex index 7be5755e8830..4aef5b7c40ea 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/fake_big_decimal_map_200_response.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/fake_big_decimal_map_200_response.ex @@ -19,6 +19,13 @@ defmodule OpenapiPetstore.Model.FakeBigDecimalMap200Response do field :someMap, {:map, :float} end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/file.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/file.ex index 2e1ce62b69cb..02581e5b2dde 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/file.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/file.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.File do field :sourceURI, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/file_schema_test_class.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/file_schema_test_class.ex index 74059653dbe6..c9139e23863d 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/file_schema_test_class.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/file_schema_test_class.ex @@ -19,6 +19,13 @@ defmodule OpenapiPetstore.Model.FileSchemaTestClass do embeds_many :files, OpenapiPetstore.Model.File end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/foo.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/foo.ex index ca428f064597..ab5644820378 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/foo.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/foo.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.Foo do field :bar, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/format_test.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/format_test.ex index ab57679ce007..b0f3a8b8b7aa 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/format_test.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/format_test.ex @@ -47,6 +47,13 @@ defmodule OpenapiPetstore.Model.FormatTest do field :pattern_with_digits_and_delimiter, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/has_only_read_only.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/has_only_read_only.ex index e14d62f4beef..98edcfc5f2ec 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/has_only_read_only.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/has_only_read_only.ex @@ -19,6 +19,13 @@ defmodule OpenapiPetstore.Model.HasOnlyReadOnly do field :foo, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/health_check_result.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/health_check_result.ex index 95d593f8f735..24829c16ac64 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/health_check_result.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/health_check_result.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.HealthCheckResult do field :NullableMessage, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/list.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/list.ex index a5161edbd44c..a1c7ff7a2335 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/list.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/list.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.List do field :"123-list", :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex index 6f43902cc954..a33d5272858a 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/map_test.ex @@ -23,6 +23,13 @@ defmodule OpenapiPetstore.Model.MapTest do field :indirect_map, {:map, :boolean} end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex index d4f903dd6952..5c26000402d6 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/mixed_properties_and_additional_properties_class.ex @@ -21,6 +21,13 @@ defmodule OpenapiPetstore.Model.MixedPropertiesAndAdditionalPropertiesClass do field :map, {:map, :any} end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/model_200_response.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/model_200_response.ex index 168ea59a311b..49bdf622c3a3 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/model_200_response.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/model_200_response.ex @@ -19,6 +19,13 @@ defmodule OpenapiPetstore.Model.Model200Response do field :class, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/name.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/name.ex index 1c430671a640..91b6215a9a73 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/name.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/name.ex @@ -23,6 +23,13 @@ defmodule OpenapiPetstore.Model.Name do field :"123Number", :integer end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/nullable_class.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/nullable_class.ex index f10b31fb43b6..b18ca5e78906 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/nullable_class.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/nullable_class.ex @@ -39,6 +39,13 @@ defmodule OpenapiPetstore.Model.NullableClass do field :object_items_nullable, {:map, {:map, :any}} end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/number_only.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/number_only.ex index 574db1a05a4a..9b25921f02c0 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/number_only.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/number_only.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.NumberOnly do field :JustNumber, :float end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/object_with_deprecated_fields.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/object_with_deprecated_fields.ex index 3a46ee417bff..05a03df2d0a9 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/object_with_deprecated_fields.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/object_with_deprecated_fields.ex @@ -23,6 +23,13 @@ defmodule OpenapiPetstore.Model.ObjectWithDeprecatedFields do embeds_one :deprecatedRef, OpenapiPetstore.Model.DeprecatedModel end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/order.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/order.ex index 7a98cd862225..0193805117a5 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/order.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/order.ex @@ -27,6 +27,13 @@ defmodule OpenapiPetstore.Model.Order do field :complete, :boolean end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_composite.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_composite.ex index c153094d7299..3d200804e502 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_composite.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_composite.ex @@ -21,6 +21,13 @@ defmodule OpenapiPetstore.Model.OuterComposite do field :my_boolean, :boolean end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_object_with_enum_property.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_object_with_enum_property.ex index b21221392dd1..f37bb6a296dd 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_object_with_enum_property.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/outer_object_with_enum_property.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.OuterObjectWithEnumProperty do field :value, :integer end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/parent_with_nullable.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/parent_with_nullable.ex index 3ee8f8a7b7a9..17cb4363dcb8 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/parent_with_nullable.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/parent_with_nullable.ex @@ -19,6 +19,13 @@ defmodule OpenapiPetstore.Model.ParentWithNullable do field :nullableProperty, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex index 361760fe0d71..abcd5c0a06bb 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/pet.ex @@ -27,6 +27,13 @@ defmodule OpenapiPetstore.Model.Pet do embeds_many :tags, OpenapiPetstore.Model.Tag end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/read_only_first.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/read_only_first.ex index 14cfb6da5c3d..30ab24eff331 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/read_only_first.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/read_only_first.ex @@ -19,6 +19,13 @@ defmodule OpenapiPetstore.Model.ReadOnlyFirst do field :baz, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/return.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/return.ex index ce7dbdd46b4c..c5b3a598f91e 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/return.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/return.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.Return do field :return, :integer end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/tag.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/tag.ex index 62a1a2059a46..385c50b8ca75 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/tag.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/tag.ex @@ -19,6 +19,13 @@ defmodule OpenapiPetstore.Model.Tag do field :name, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/test_inline_freeform_additional_properties_request.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/test_inline_freeform_additional_properties_request.ex index 601ceedb5973..03b368bd378b 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/test_inline_freeform_additional_properties_request.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/test_inline_freeform_additional_properties_request.ex @@ -17,6 +17,13 @@ defmodule OpenapiPetstore.Model.TestInlineFreeformAdditionalPropertiesRequest do field :someProperty, :string end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/lib/openapi_petstore/model/user.ex b/samples/client/petstore/elixir/lib/openapi_petstore/model/user.ex index 78eded1e95de..efb601cb6a64 100644 --- a/samples/client/petstore/elixir/lib/openapi_petstore/model/user.ex +++ b/samples/client/petstore/elixir/lib/openapi_petstore/model/user.ex @@ -31,6 +31,13 @@ defmodule OpenapiPetstore.Model.User do field :userStatus, :integer end + @spec from_params(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def from_params(params) do + %__MODULE__{} + |> changeset(params) + |> Ecto.Changeset.apply_action(:insert) + end + @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(%__MODULE__{} = struct, params) do struct diff --git a/samples/client/petstore/elixir/test/any_test.exs b/samples/client/petstore/elixir/test/any_test.exs index 527d1600a57a..3305a60adae8 100644 --- a/samples/client/petstore/elixir/test/any_test.exs +++ b/samples/client/petstore/elixir/test/any_test.exs @@ -3,13 +3,15 @@ defmodule AnyTest do alias OpenapiPetstore.Model.Any, as: Model test "decode all properties (not nil)" do - assert %{ - "@type": "3fa85f64-5717-4562-b3fc-2c963f66afa6" - } - |> then(fn params -> Model.changeset(%Model{}, params) end) - |> Ecto.Changeset.apply_action!(:insert) == - %Model{ - "@type": "3fa85f64-5717-4562-b3fc-2c963f66afa6" - } + {:ok, model} = + %{ + "@type": "3fa85f64-5717-4562-b3fc-2c963f66afa6" + } + |> Model.from_params + + assert model == + %Model{ + "@type": "3fa85f64-5717-4562-b3fc-2c963f66afa6" + } end end diff --git a/samples/client/petstore/elixir/test/deserializer_test.exs b/samples/client/petstore/elixir/test/deserializer_test.exs index aac7a6822e09..2be9bd06ffc1 100644 --- a/samples/client/petstore/elixir/test/deserializer_test.exs +++ b/samples/client/petstore/elixir/test/deserializer_test.exs @@ -29,10 +29,9 @@ defmodule DeserializerTest do """ test "can deserialize valid JSON" do - pet = + {:ok, pet} = JSON.decode!(@valid_json) - |> then(fn params -> Pet.changeset(%Pet{}, params) end) - |> Ecto.Changeset.apply_action!(:insert) + |> Pet.from_params assert pet == %Pet{ diff --git a/samples/client/petstore/elixir/test/format_test.exs b/samples/client/petstore/elixir/test/format_test.exs index c1951a5b375a..1180b94829ad 100644 --- a/samples/client/petstore/elixir/test/format_test.exs +++ b/samples/client/petstore/elixir/test/format_test.exs @@ -3,84 +3,88 @@ defmodule FormatTest do alias OpenapiPetstore.Model.FormatTest test "decode all properties (not nil)" do - assert %{ - integer: 1, - int32: 2, - int64: 3, - number: 4.1, - float: 5.2, - double: 6.3, - decimal: "7.4", - string: "Hello world!", - byte: "U3dhZ2dlciByb2Nrcw==", - binary: <<1, 2, 3>>, - date: "2013-10-20", - dateTime: "2013-10-20T19:20:30+01:00", - uuid: "3fa85f64-5717-4562-b3fc-2c963f66afa6", - password: "green?horse", - pattern_with_digits: "1234567890", - pattern_with_digits_and_delimiter: "Image_01" - } - |> then(fn params -> FormatTest.changeset(%FormatTest{}, params) end) - |> Ecto.Changeset.apply_action!(:insert) == - %FormatTest{ - integer: 1, - int32: 2, - int64: 3, - number: 4.1, - float: 5.2, - double: 6.3, - decimal: 7.4, - string: "Hello world!", - byte: "U3dhZ2dlciByb2Nrcw==", - binary: <<1, 2, 3>>, - date: ~D[2013-10-20], - dateTime: ~U[2013-10-20 18:20:30Z], - uuid: "3fa85f64-5717-4562-b3fc-2c963f66afa6", - password: "green?horse", - pattern_with_digits: "1234567890", - pattern_with_digits_and_delimiter: "Image_01" - } + {:ok, model} = + %{ + integer: 1, + int32: 2, + int64: 3, + number: 4.1, + float: 5.2, + double: 6.3, + decimal: "7.4", + string: "Hello world!", + byte: "U3dhZ2dlciByb2Nrcw==", + binary: <<1, 2, 3>>, + date: "2013-10-20", + dateTime: "2013-10-20T19:20:30+01:00", + uuid: "3fa85f64-5717-4562-b3fc-2c963f66afa6", + password: "green?horse", + pattern_with_digits: "1234567890", + pattern_with_digits_and_delimiter: "Image_01" + } + |> FormatTest.from_params + + assert model == + %FormatTest{ + integer: 1, + int32: 2, + int64: 3, + number: 4.1, + float: 5.2, + double: 6.3, + decimal: 7.4, + string: "Hello world!", + byte: "U3dhZ2dlciByb2Nrcw==", + binary: <<1, 2, 3>>, + date: ~D[2013-10-20], + dateTime: ~U[2013-10-20 18:20:30Z], + uuid: "3fa85f64-5717-4562-b3fc-2c963f66afa6", + password: "green?horse", + pattern_with_digits: "1234567890", + pattern_with_digits_and_delimiter: "Image_01" + } end test "decode all properties (some are nil)" do - assert %{ - integer: nil, - int32: nil, - int64: nil, - number: 4.1, - float: nil, - double: nil, - decimal: nil, - string: nil, - byte: "U3dhZ2dlciByb2Nrcw==", - binary: nil, - date: "2013-10-20", - dateTime: nil, - uuid: nil, - password: "green?horse", - pattern_with_digits: nil, - pattern_with_digits_and_delimiter: nil - } - |> then(fn params -> FormatTest.changeset(%FormatTest{}, params) end) - |> Ecto.Changeset.apply_action!(:insert) == - %FormatTest{ - integer: nil, - int32: nil, - int64: nil, - number: 4.1, - float: nil, - double: nil, - decimal: nil, - string: nil, - byte: "U3dhZ2dlciByb2Nrcw==", - binary: nil, - date: ~D[2013-10-20], - dateTime: nil, - uuid: nil, - password: "green?horse", - pattern_with_digits: nil, - pattern_with_digits_and_delimiter: nil - } + {:ok, model} = + %{ + integer: nil, + int32: nil, + int64: nil, + number: 4.1, + float: nil, + double: nil, + decimal: nil, + string: nil, + byte: "U3dhZ2dlciByb2Nrcw==", + binary: nil, + date: "2013-10-20", + dateTime: nil, + uuid: nil, + password: "green?horse", + pattern_with_digits: nil, + pattern_with_digits_and_delimiter: nil + } + |> FormatTest.from_params + + assert model == + %FormatTest{ + integer: nil, + int32: nil, + int64: nil, + number: 4.1, + float: nil, + double: nil, + decimal: nil, + string: nil, + byte: "U3dhZ2dlciByb2Nrcw==", + binary: nil, + date: ~D[2013-10-20], + dateTime: nil, + uuid: nil, + password: "green?horse", + pattern_with_digits: nil, + pattern_with_digits_and_delimiter: nil + } end end diff --git a/samples/client/petstore/elixir/test/mixed_properties_and_additional_properties_class_test.exs b/samples/client/petstore/elixir/test/mixed_properties_and_additional_properties_class_test.exs index 375bffa54049..5bc1069d41da 100644 --- a/samples/client/petstore/elixir/test/mixed_properties_and_additional_properties_class_test.exs +++ b/samples/client/petstore/elixir/test/mixed_properties_and_additional_properties_class_test.exs @@ -4,45 +4,49 @@ defmodule MixedPropertiesAndAdditionalPropertiesClass do alias OpenapiPetstore.Model.Animal test "decode all properties (not nil)" do - assert %{ - uuid: "3fa85f64-5717-4562-b3fc-2c963f66afa6", - dateTime: "2013-10-20T19:20:30+01:00", - map: %{ - "doggie" => %{"className" => "DOG", "color" => "yellow", "breed" => "Shiba Inu"}, - "meow" => %{"className" => "CAT", "color" => "white", "declawed" => false} - } - } - |> then(fn params -> Model.changeset(%Model{}, params) end) - |> Ecto.Changeset.apply_action!(:insert) == - %Model{ - uuid: "3fa85f64-5717-4562-b3fc-2c963f66afa6", - dateTime: ~U[2013-10-20 18:20:30Z], - map: %{ - # TODO values should be Dog and Cat structs instead of an Animal - "doggie" => %Animal{ - className: "DOG", - color: "yellow" - }, - "meow" => %Animal{ - className: "CAT", - color: "white" - } - } - } + {:ok, model} = + %{ + uuid: "3fa85f64-5717-4562-b3fc-2c963f66afa6", + dateTime: "2013-10-20T19:20:30+01:00", + map: %{ + "doggie" => %{"className" => "DOG", "color" => "yellow", "breed" => "Shiba Inu"}, + "meow" => %{"className" => "CAT", "color" => "white", "declawed" => false} + } + } + |> Model.from_params + + assert model == + %Model{ + uuid: "3fa85f64-5717-4562-b3fc-2c963f66afa6", + dateTime: ~U[2013-10-20 18:20:30Z], + map: %{ + # TODO values should be Dog and Cat structs instead of an Animal + "doggie" => %Animal{ + className: "DOG", + color: "yellow" + }, + "meow" => %Animal{ + className: "CAT", + color: "white" + } + } + } end test "decode all properties (nil)" do - assert %{ - uuid: nil, - dateTime: nil, - map: nil - } - |> then(fn params -> Model.changeset(%Model{}, params) end) - |> Ecto.Changeset.apply_action!(:insert) == - %Model{ - uuid: nil, - dateTime: nil, - map: nil - } + {:ok, model} = + %{ + uuid: nil, + dateTime: nil, + map: nil + } + |> Model.from_params + + assert model == + %Model{ + uuid: nil, + dateTime: nil, + map: nil + } end end diff --git a/samples/client/petstore/elixir/test/outer_enum_test.exs b/samples/client/petstore/elixir/test/outer_enum_test.exs index c865e2d2d46c..e632cb99c3f7 100644 --- a/samples/client/petstore/elixir/test/outer_enum_test.exs +++ b/samples/client/petstore/elixir/test/outer_enum_test.exs @@ -15,10 +15,9 @@ defmodule OuterEnumTest do @tag timeout: :infinity test "json_decode/2 with valid JSON" do - enum_test = + {:ok, enum_test} = JSON.decode!(@valid_json) - |> then(fn params -> EnumTest.changeset(%EnumTest{}, params) end) - |> Ecto.Changeset.apply_action!(:insert) + |> EnumTest.from_params assert enum_test == %EnumTest{