raml-org / raml-spec

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

RAML 1.0 Arrays: inside an object or plain array? #537

Open thevangelist opened 8 years ago

thevangelist commented 8 years ago

Here's what RAML 1.0 says about arrays: https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md#array-type

However the specifications isn't exactly clear whether to use a Array... Assuming I have a of body: Pokemon[], where each Pokemon is:

type: object
description: Pokemon
properties:
  name:
    type: string
    description: Pokemon name
  description:
    type: string
    description: Description of Pokemon

Which is the correct JSON, A or B?

A)

{
    "pokemons": [{
        "name": "Pikachu",
        "description": "Electric"
    }, {
        "name": "Bulbasaur",
        "description": "Dual-type Grass/Poison"
    }]
}

or B)

[{
    "name": "Pikachu",
    "description": "Electric"
}, {
    "name": "Bulbasaur",
    "description": "Dual-type Grass/Poison"
}]

Both are valid json according to: http://jsonlint.com/

sichvoge commented 8 years ago

Really depends. I would say its mostly A) since you always use a key-value pair for properties in RAML data types. In your example you would have:

types:
  Pokemon:
  PokemonGo:
    properties:
      pokemons: Pokemon[]

The only place where B) can be relevant is if you have something like:

types:
  Pokemon:
  Pokemons: Pokemon[]
thevangelist commented 8 years ago

Hmm, shouldn't the specification be unambiguous? Say there's two companies implementing equivalents on each side and if the spec isn't unambiguous, both sides can implement it differently?

sichvoge commented 8 years ago

Its unambiguous as far as you can get with plain English. The actual output just depends if you say a type is an array or a property. Same in JSON schema.

freddrake commented 8 years ago

For body: Pokemon[], I'd expect B only.

jsonlint.com is irrelevant here; both examples are JSON, but only B conforms with body: Pokemon[].

sichvoge commented 8 years ago

@freddrake so you think we have to clarify anything in the specification? if yes, there are multiple places but maybe we should provide an additional reference document that explains how RAML data types do map into JSON schema?

freddrake commented 8 years ago

@sichvoge I think the specification is clear. If more examples are required (indicated by questions like this coming up), an informative document can be added. My interpretation is based on interpreting what's in the spec, without bringing in outside expectations based on what I'd like to see in an actual API.

(I think it's clear that my expectation of RAML is that I can use it to describe an API accurately and unambiguously, even if that API doesn't conform to best practices. Because humans have a hard time agreeing on the later. Best practices considerations are best left to linters.)

sichvoge commented 8 years ago

OK. I think an informative document makes some sense especially around mapping into JSON schema. If one would like to start with that, go for it :) Otherwise, it would take me some time to consolidate something

stevenroose commented 7 years ago

I think this is cleared out, and can be closed.

If anyone has a spare minute, quick question: is it possible to define arrays of objects inline without creating a global type? Something like

[...]
application/json:
  type: object[]
  properties:
    name: string
    age: integer
  example: |
    [
      {
        "name": "harry",
        "age": 18
      }
    ]
sichvoge commented 7 years ago

Hi, you should be able to do this without using type expressions ([]). In your case, the following works:

[...]
application/json:
  type: array
  items:
    type: object
    properties:
      name: string
      age: integer
    example: |
      [
        {
          "name": "harry",
          "age": 18
        }
      ]
stevenroose commented 7 years ago

@sichvoge I found out, but thanks a lot for the swift response! (The example key in your snippet needs to be indented one level lower, though :)

sichvoge commented 7 years ago

Ups, you are right :D

thanl223 commented 6 years ago

In Anypoint Studio Design center, the following seems like it would work; the API console renders nicely with no errors.

  application/json:
    properties: 
      Customer:
        type: object
        properties: 
          firstName:
          lastName:
          titleCode:
          password:
          carrier:
          MId:
            description: ******ID
          email:
      order:
        type: object
        properties: 
          cart:
            type: object
            properties: 
              txnId:
              accountNumber:
              storeFrontId:
              shipMethod:
              sendToFulfillment:
              byodErrorEmail:
              orderCompletionEmail:
              cartItems:
                type: array
                items:
                  type: object
                  properties:
                    coverageZip: string
              teamId:
              referringMDN:
              securityPIN:
              email:
              userName:
              language:
    example: |
      {
        "Customer": {
          "firstName": "Jack",
          "lastName": "Ophaltrades",
          "titleCode": "Mr.",
          "password": "somepassword",
          "carrier": "Verizon",
          "MId": "1234567",
          "email": "jack.ophaltrades@someemaildomain.com"
        },
        "order": {
          "cart": {
            "txnId": "3234234",
            "accountNumber": "stri123456ng",
            "storeFrontId": "1234",
            "shipMethod": "UPS Ground",
            "sendToFulfillment": "Yes",
            "byodErrorEmail": "byodemail@someemaildomain.com",
            "orderCompletionEmail": "true",
            "cartItems": 
              [
                  { 
                    "coverageZip": "90210"
                  },
                  {
                    "coverageZip": "23423"
                  }
              ],
            "teamId": "1234",
            "referringMDN": "16",
            "securityPIN": "1561",
            "email": "someemail@someemaildomain.com",
            "userName": "username",
            "language": "ENG"
          }
        }
      }

However, when I "try it", the HTTP response from the mocking service yields this error.

{ "error": "body: order: cart: cartItems: Cannot read property '#' of undefined" }

Thoughts as to what is wrong?