diff --git a/spec/onyx-rest/action_spec.cr b/spec/onyx-rest/action_spec.cr index 9c04f9d..b8f1e2d 100644 --- a/spec/onyx-rest/action_spec.cr +++ b/spec/onyx-rest/action_spec.cr @@ -57,7 +57,7 @@ class JSONAction params do json require: true, any_content_type: true do - type user do + type user, nilable: true do type name : String type email : String end @@ -65,7 +65,7 @@ class JSONAction end def call - context.response << "#{params.json.user.name}, #{params.json.user.email}" + context.response << "#{params.json.user.try &.name}, #{params.json.user.try &.email}" end end @@ -120,6 +120,26 @@ describe Onyx::REST::Action do end context "JSON action" do + context "with empty JSON" do + it do + response = client.post("/json", + body: "{}" + ) + response.status_code.should eq 200 + response.body.should eq ", " + end + end + + context "with empty user" do + it do + response = client.post("/json", + body: %Q[{"user": null}] + ) + response.status_code.should eq 200 + response.body.should eq ", " + end + end + it do response = client.post("/json", body: %Q[{"user": {"name": "John", "email": "foo@example.com"}}] diff --git a/src/onyx-rest/endpoint/params/form.cr b/src/onyx-rest/endpoint/params/form.cr index defd367..2c2e249 100644 --- a/src/onyx-rest/endpoint/params/form.cr +++ b/src/onyx-rest/endpoint/params/form.cr @@ -93,7 +93,7 @@ module Onyx::REST::Endpoint include ::HTTP::Params::Serializable {% verbatim do %} - macro type(argument, **options, &block) + macro type(argument, nilable = false, **options, &block) {% if block %} {% unless options.empty? %} @[::HTTP::Param({{**options}})] @@ -102,9 +102,9 @@ module Onyx::REST::Endpoint {% if argument.is_a?(Path) %} {% raise "Cannot declare namespaced nested query parameter" if argument.names.size > 1 %} - getter {{argument.names.first.underscore}} : {{argument.names.first.camelcase.id}} + getter {{argument.names.first.underscore}} : {{argument.names.first.camelcase.id}}{{" | Nil".id if nilable}} {% elsif argument.is_a?(Call) %} - getter {{argument.name.underscore}} : {{argument.name.camelcase.id}} + getter {{argument.name.underscore}} : {{argument.name.camelcase.id}}{{" | Nil".id if nilable}} {% else %} {% raise "BUG: Unhandled argument type #{argument.class_name}" %} {% end %} diff --git a/src/onyx-rest/endpoint/params/json.cr b/src/onyx-rest/endpoint/params/json.cr index b492596..5839112 100644 --- a/src/onyx-rest/endpoint/params/json.cr +++ b/src/onyx-rest/endpoint/params/json.cr @@ -87,7 +87,7 @@ module Onyx::REST::Endpoint include JSON::Serializable {% verbatim do %} - macro type(argument, **options, &block) + macro type(argument, nilable = false, **options, &block) {% if block %} {% unless options.empty? %} @[JSON::Field({{**options}})] @@ -96,9 +96,9 @@ module Onyx::REST::Endpoint {% if argument.is_a?(Path) %} {% raise "Cannot declare namespaced nested query parameter" if argument.names.size > 1 %} - getter {{argument.names.first.underscore}} : {{argument.names.first.camelcase.id}} + getter {{argument.names.first.underscore}} : {{argument.names.first.camelcase.id}}{{" | Nil".id if nilable}} {% elsif argument.is_a?(Call) %} - getter {{argument.name.underscore}} : {{argument.name.camelcase.id}} + getter {{argument.name.underscore}} : {{argument.name.camelcase.id}}{{" | Nil".id if nilable}} {% else %} {% raise "BUG: Unhandled argument type #{argument.class_name}" %} {% end %} diff --git a/src/onyx-rest/endpoint/params/query.cr b/src/onyx-rest/endpoint/params/query.cr index efb1a29..1f31011 100644 --- a/src/onyx-rest/endpoint/params/query.cr +++ b/src/onyx-rest/endpoint/params/query.cr @@ -42,7 +42,7 @@ module Onyx::REST::Endpoint include ::HTTP::Params::Serializable {% verbatim do %} - macro type(argument, **options, &block) + macro type(argument, nilable = false, **options, &block) {% if block %} {% unless options.empty? %} @[::HTTP::Param({{**options}})] @@ -51,9 +51,9 @@ module Onyx::REST::Endpoint {% if argument.is_a?(Path) %} {% raise "Cannot declare namespaced nested query parameter" if argument.names.size > 1 %} - getter {{argument.names.first.underscore}} : {{argument.names.first.camelcase.id}} + getter {{argument.names.first.underscore}} : {{argument.names.first.camelcase.id}}{{" | Nil".id if nilable}} {% elsif argument.is_a?(Call) %} - getter {{argument.name.underscore}} : {{argument.name.camelcase.id}} + getter {{argument.name.underscore}} : {{argument.name.camelcase.id}}{{" | Nil".id if nilable}} {% else %} {% raise "BUG: Unhandled argument type #{argument.class_name}" %} {% end %}