raml-org / raml-spec

RAML Specification
http://raml.org
3.87k stars 858 forks source link

Type declaration for a union type #530

Open antoniogarrote opened 8 years ago

antoniogarrote commented 8 years ago

Hi.

I'm working on a particular use case: generating stand-alone type declarations not using any user introduced type names. This is useful in situations where you cannot keep the name-to-declaration mapping information and I think it makes the specification more consistent.

For other types this can be easily achieved just replacing the name of the type by its declaration in a recursive way. However, if I understand the spec correctly, union types can only be introduced using type expressions involving type names.

I would like to express the same union type with a normal type declaration.

A possible syntax could be:

type: union
of: 
  - TypeA
  # ...
  - TypeN

In this way I could express this RAML type 'schema':

types:
  TypeA:
    type: object
    properties:
      a:
        type: string
  TypeB:
    type: object
    properties:
      b:
        type: string
  TypeUnion: TypeA | TypeB

In this stand-alone inline type declaration:

#%RAML 1.0
type: union
of:
  - type: object
    properties:
      a:
        type: string
  - type: object
    properties:
      b:
        type: string
sichvoge commented 8 years ago

For me that makes a lot of sense. Why? Its easier to work with "real types" such as array, number, object, instead of having to parse the type expression to find out if its multiple inheritance, union, or an array type. Union is actually described in our type hierarchy on the same level as all the other types. An array for example can be expressed as a expression string[] or using type: array. Why not doing the same for union. I like the idea and it would make a lot of things easier when processing types.

BTW, I would also suggest to mention that a processor needs to expand expressions like string[] and Cat | Dog to its respective "full" type. Not sure how else to describe that, but if the input for a processor or parser in general is:

types:
  ArrayA: string[]
  TypeA:
    type: object
    properties:
      a:
        type: string
  TypeB:
    type: object
    properties:
      b:
        type: string
  TypeUnion: TypeA | TypeB

the output of that parser should be:

types:
  ArrayA: 
    type: array
    items: string
  TypeA:
    type: object
    properties:
      a:
        type: string
  TypeB:
    type: object
    properties:
      b:
        type: string
  TypeUnion: 
    type: union
    of:
      - TypeA
      - TypeB

Obviously we can also fully expand types but you might loose too many information. That is something I am not sure about.

Again [] and | for me is just a syntactical sugar that makes it easier to create types, but is hard for someone to work with. If the approach is consistent (you always have a type property w/o those expressions) it will be a huge benefit for the tooling development.

sichvoge commented 8 years ago

BTW, the workbench actually suggest a type called union already :)

sichvoge commented 8 years ago

@antoniogarrote any objections to call of -> anyOf. Are there any restrictions on the number of elements that you can define in anyOf? For example, is the following possible:

type: union
anyOf:
  - type: object
    properties:
      a:
        type: string

How would you define the value of anyOf? Can you help a little bit better to understand your intensions?

deem0n commented 8 years ago

Hi all. I have some feedback on the current RAML 1.0 Union Type support. Assuming we split every type definition in its own RAML file and finally want to assemble Union type.

For example, having this correct file:

#%RAML 1.0 DataType
# guid.raml
type: string
minLength: 36
maxLength: 36
pattern: ^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$

we can not have something like this:

#%RAML 1.0 DataType
# uniontype.raml
    type: integer | GUID

as there is no way to refer to guid.raml I guess simple !include support would do:

#%RAML 1.0 DataType
# uniontype.raml
    type: integer | !include guid.raml

Any idea if such composition possible in some way with RAML 1.0 ?

machaval commented 8 years ago

You should use libraries this is the best way to reuse any element as later you can reference it.

On Tue, Aug 23, 2016 at 1:20 PM, deem0n notifications@github.com wrote:

Hi all. I have some feedback on the current RAML 1.0 Union Type support. Assuming we split every type definition in its own RAML file and finally want to assemble Union type.

For example, having this correct file:

`#%RAML 1.0 DataType guid.raml

type: string minLength: 36 maxLength: 36 pattern: ^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$`

we can not have something like this:

`#%RAML 1.0 DataType uniontype.raml

DatasetID: type: integer | GUID ` as there is no way to refer to guid.raml I guess simple !include support would do:

`#%RAML 1.0 DataType uniontype.raml

DatasetID: type: integer | !include guid.raml `

Any idea if such composition possible in some way with RAML 1.0 ?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/raml-org/raml-spec/issues/530#issuecomment-241789462, or mute the thread https://github.com/notifications/unsubscribe-auth/AAGMePO_jwtaF3fScVpmFOt9FpyqSIhRks5qix23gaJpZM4JL7NJ .

deem0n commented 8 years ago

Libraries are very flexible, but it seems all my types will have common prefix, which might not be desired:

#%RAML 1.0

uses:
  TP: types.raml
...
.......
    type: TP.MyType

My point was that #%RAML 1.0 DataType fragment is not yet powerful enough to support data types modeling and file reuse. The only missing part is references to types defined in other #%RAML 1.0 DataType files without need to use libraries.

sichvoge commented 8 years ago

With RAML data type, and thats only for them, you can easily do includes on fragments. For example, assume you have the following:

#%RAML 1.0 DataType
# annotation.raml

usage: Describes the content of a single annotation.

type: object
properties:
  /^[\\w-]+$/:
    type: object
    description: The data instance of a specific annotation.
#%RAML 1.0 DataType

type: object
properties:
  annotations?:
    description: A list of applied annotations to a specific node.
    type: array
    items: !include annotation.raml # here you point to another fragment
  value:
    type: string
    description: Contains the value of this node.

BUT that does not work for multiple inheritance AND union as the only values allowed are references to type identifiers. Hence for that you would need to use libraries. We are currently thinking about how to improve that, but we should not discuss that in this ticket. If you have an idea, you are very welcome to create a new issue ;)

mthurmaier-ms commented 3 years ago

Hi, can I please ask what the status is of this idea in RAML 1.x?
My 2 cents is that there absolutely be a "type: union", but the word "of" is extraneous. You should be able to do: type: union [ type1, type2 ] with ass many items in the union that you want OR use the YAML way for arrays and do: `type: union

For each of the type1, type2, etc, one should be able to replace the type with a !include _xxx.raml_ where xxx.raml contains a #%RAML 1.x DataType.

Thoughts?