From 7bc5a21c6339c0a4dbad2d1cf3b85d48a058581e Mon Sep 17 00:00:00 2001 From: Dmitry Shpagin Date: Wed, 3 Jul 2024 21:56:37 +0300 Subject: [PATCH 1/2] Casting of arrays into specified Schemas --- lib/open_api_spex/cast.ex | 6 +++- test/cast_test.exs | 63 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/lib/open_api_spex/cast.ex b/lib/open_api_spex/cast.ex index 269cf3f4..b386e727 100644 --- a/lib/open_api_spex/cast.ex +++ b/lib/open_api_spex/cast.ex @@ -207,7 +207,11 @@ defmodule OpenApiSpex.Cast do def cast(%__MODULE__{schema: %{type: _other}} = ctx), do: error(ctx, {:invalid_schema_type}) - def cast(%{} = ctx), do: cast(struct(__MODULE__, ctx)) + def cast(%__MODULE__{value: struct, schema: schema_module} = ctx) + when is_struct(struct) and is_atom(schema_module), + do: cast(ctx.schema.schema(), ctx.value) + + def cast(%{} = ctx), do: cast(struct(__MODULE__, ctx.value)) def cast(ctx) when is_list(ctx), do: cast(struct(__MODULE__, ctx)) # Add an error diff --git a/test/cast_test.exs b/test/cast_test.exs index 1cb2baf5..0df8e9d1 100644 --- a/test/cast_test.exs +++ b/test/cast_test.exs @@ -6,6 +6,69 @@ defmodule OpenApiSpec.CastTest do def cast(ctx), do: Cast.cast(ctx) + describe "SubScheme with array" do + defmodule User do + defstruct [:email, :permissions] + end + + defmodule Permission do + defstruct [:name, :some_other_field] + end + + defmodule UsersSchemas do + alias OpenApiSpex.Schema + + defmodule PermissionSchema do + @moduledoc false + require OpenApiSpex + + OpenApiSpex.schema(%{ + title: "Permission", + type: :object, + properties: %{ + name: %Schema{type: :string} + }, + required: [:name, :some_other_field] + }) + end + + defmodule UserSchema do + @moduledoc false + require OpenApiSpex + + OpenApiSpex.schema(%{ + title: "User", + type: :object, + properties: %{ + email: %Schema{type: :string}, + permissions: %Schema{type: :array, items: PermissionSchema} + }, + required: [:email, :permissions] + }) + end + end + + test "Correct casting of sub arrays" do + permissions = [ + %Permission{name: "Work", some_other_field: 1}, + %Permission{name: "Rest", some_other_field: 2}, + %Permission{name: "Smile", some_other_field: 3} + ] + + user = %User{email: "happy_admin@email.com", permissions: permissions} + + assert {:ok, + %UsersSchemas.UserSchema{ + email: "happy_admin@email.com", + permissions: [ + %UsersSchemas.PermissionSchema{name: "Work"}, + %UsersSchemas.PermissionSchema{name: "Rest"}, + %UsersSchemas.PermissionSchema{name: "Smile"} + ] + }} == OpenApiSpex.cast_value(user, UsersSchemas.UserSchema.schema()) + end + end + describe "cast/1" do test "unknown schema type" do assert {:error, [error]} = cast(value: "string", schema: %Schema{type: :nope}) From 327e187394e9c5b91700ff258b67b8a99d117f59 Mon Sep 17 00:00:00 2001 From: Dmitry Shpagin Date: Wed, 3 Jul 2024 22:14:10 +0300 Subject: [PATCH 2/2] fixup! Casting of arrays into specified Schemas --- lib/open_api_spex/cast.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/open_api_spex/cast.ex b/lib/open_api_spex/cast.ex index b386e727..b4b8c051 100644 --- a/lib/open_api_spex/cast.ex +++ b/lib/open_api_spex/cast.ex @@ -211,7 +211,7 @@ defmodule OpenApiSpex.Cast do when is_struct(struct) and is_atom(schema_module), do: cast(ctx.schema.schema(), ctx.value) - def cast(%{} = ctx), do: cast(struct(__MODULE__, ctx.value)) + def cast(%{} = ctx), do: cast(struct(__MODULE__, ctx)) def cast(ctx) when is_list(ctx), do: cast(struct(__MODULE__, ctx)) # Add an error