yahehe / Nancy.Swagger

Nancy plugin for generated API documentation in Swagger format.
MIT License
133 stars 60 forks source link

How to describe models #109

Closed dennisdoomen closed 7 years ago

dennisdoomen commented 7 years ago

I have a couple of routes that return non-primitive types. I know how to include them in the swagger specification, but how do I influence the types and documentation of the properties on those models. E.g. a DateTime property is always exposed in the Swagger spec as a string.

jnallard commented 7 years ago

We should probably have DateTime reflected as a string automatically. (I thought we did).

Anyways, you can make use of SwaggerTypeMapping: https://github.com/yahehe/Nancy.Swagger/blob/master/src/Nancy.Swagger/SwaggerTypeMapping.cs

It should allow you to represent any type as whatever type you want. I use it on of my projects to represent a Units.Net struct as a string and I wrote a custom json serializer/deserializer to make the conversion.

For DateTime you would want a line like: SwaggerTypeMapping.AddTypeMapping(typeof(DateTime), typeof(string));

I'll add this info to the wiki.

dennisdoomen commented 7 years ago

I'll try that. Thanks.

dennisdoomen commented 7 years ago

Oh wait, I want to do the reverse. My DateTime property is now exposes as a string in the Swagger spec. But I really want it to be a DateTime.

jnallard commented 7 years ago

So the DateTime is represented by a string by default? And you want to avoid that? I might need to add some sort of setting for that. Or you could add a DateTimeDto class with the same properties and add a mapping to that.

yahehe commented 7 years ago

Datetime is a swagger primitive, represented as a string as specified by https://xml2rfc.tools.ietf.org/public/rfc/html/rfc3339.html#anchor14 What use case are you trying to support where you can't serialize to/from the string?

dennisdoomen commented 7 years ago

It's not a problem of serialization/deserilization. It's more that I expected the swagger spec to state it was a date/time.

jnallard commented 7 years ago

Can you show an example or what you're getting and then what you wanted/expected?

yahehe commented 7 years ago

This sounds like you have an issue with the swagger spec?

yahehe commented 7 years ago

Is this still a problem you have @dennisdoomen ?

dennisdoomen commented 7 years ago

No, I've worked around it. Thank you.

bsmithvt commented 7 years ago

@dennisdoomen , can you please describe your workaround? I'm having the same issue, and I tried doing this => SwaggerTypeMapping.AddTypeMapping(typeof(DateTime), typeof(DateTime)); to no avail. My Nancy Swagger doc generator is still generating DateTime types as string. Thank you.

yahehe commented 7 years ago

What's your use case for that if you don't mind me asking? Datetimes are supposed to be represented as strings as per the swagger specification. I'd like to know more about why this is insufficient before adding an 'official' workaround

yahehe commented 7 years ago

That said I would also expect AddTypeMapping to allow you to override a default

bsmithvt commented 7 years ago

@yahehe, thanks for the response. We have an API that returns an entity which contains a valid DateTime property. We do not convert it to a string in the API response, so we want our Swagger documentation to accurately reflect what's in the response. Consumers of our API will think the property is a string based on the documentation, which is incorrect.

yahehe commented 7 years ago

Interesting, so it's a raw byte array (or similar)? If this is urgent for you feel free to make a PR, it'll take me at least a few days before I can do anything

jnallard commented 7 years ago

What does the JSON look like?

SwaggerTypeMapping.AddTypeMapping(typeof(DateTime), typeof(DateTime)); won't work because the type mapping happens before the actual modeling. So DateTime will map to DateTime, but DateTime will still be treated like a primitive string.

What you could do (as I said above) is SwaggerTypeMapping.AddTypeMapping(typeof(DateTime), typeof(DateTimeDTO)); where DateTimeDTO is a class that has all the properties from DataTime you want the consumer to be aware of. I think that would work. If not, you might have to have the swagger model say it's a DateTimeDTO. (Which should be easy to do - I can tell you how to do it, but I'd need to know how you're modeling the data)

I personally would dislike adding other code to manage this, because, as @yahehe said, Datetime should be represented as a string in the Swagger Spec.