biocad / openapi3

OpenAPI 3.0 data model
BSD 3-Clause "New" or "Revised" License
39 stars 53 forks source link

Mismatch between ToJSON and ToSchema with nullary single-record constructor #81

Open jkarni opened 1 year ago

jkarni commented 1 year ago
ghci> data Foo = Foo deriving stock (Generic)
ghci> genericToJSON defaultOptions Foo
Array []
 ghci> encodePretty $ runDeclare (genericDeclareSchema (fromAesonOptions (defaultOptions)) (Proxy :: Proxy Foo)) mempty
"[\n    {},\n    {\n        \"enum\": [\n            \"Foo\"\n        ],\n        \"type\": \"string\"\n    }\n]"

Now, you can get Aeson to behave in the way openapi3 does by using tagSingleConstructors :+1:

ghci> genericToJSON (defaultOptions { tagSingleConstructors = True}) Foo
String "Foo"

But with tagSingleConstructors you get a mismatch when the record is not nullary:

ghci> data Bar = Bar Int deriving stock (Generic)
ghci> genericToJSON (defaultOptions { tagSingleConstructors = True}) (Bar 5)
Object (fromList [("contents",Number 5.0),("tag",String "Bar")])
ghci> encodePretty $ runDeclare (genericDeclareSchema (fromAesonOptions (defaultOptions { tagSingleConstructors = True})) (Proxy :: Proxy Bar)) mempty
"[\n    {},\n    {\n        \"maximum\": 9223372036854775807,\n        \"minimum\": -9223372036854775808,\n        \"type\": \"integer\"\n    }\n]"

Which is already known, but means that even if you can modify your encoding to navigate openapi/aeson support, there isn't a single Options that works in all cases.

Am happy to help - though if you have any insights on where to start, let me know!

(See also #55)