apiaryio / mson

Markdown Syntax for Object Notation
MIT License
899 stars 181 forks source link

Repeating a data structure with different values #94

Open zeluspudding opened 5 years ago

zeluspudding commented 5 years ago

I have many places in my API where I will need to describe a list of objects. Each object has the same keys / structure but different values. How can I tweak the values of each instance of some data structure while retaining all the original type, description, etc of the original structure?

for example if I had the following data structure Restaurant

# Data Structures
## Restaurant (object)
+ restaurant_name: McDonald's (string, required) - The name of this restaurant
+ years_of_operation: 54 (number, required) - The number of years since established

Then, let's say I want to instantiate several Restaurants in a GET response like so:

### List all restaurants [GET /restaurants]

+ Response 200 (application/json)
    + Attributes
        + data (array)
            + (Restaurant)
            + (Restaurant)
                + restaurant_name: Bob Evans
                + years_of_operation: 23
            + (Restaurant)
                + restaurant_name: Eataly
                + years_of_operation: 16

the JSON body would look like this (note how years_of_operation for Bob Evans and Eatly are now numbers)

image

and the rendered documentation will only show this (the descriptions for restaurant_name and years_of_operation for Bob Evans and Eatly are now missing)

image

I thought that MSON would carry over those descriptions and type definitions. Otherwise, I have to update a description (or type, requirement, etc) everywhere that data structure is used... but I was under the impression this is a sort of problem MSON is supposed to solve? Am I doing something silly?

zeluspudding commented 5 years ago

I've updated my question with better examples.

kylef commented 5 years ago

The reason they are strings and not numbers is because the default type is string and the value isn't set as a number type. If you change the following they will become numbers:

+ `years_of_operation`: 23 (number)
+ `years_of_operation`: 16 (number)
zeluspudding commented 5 years ago

Right - that's what I thought MSON would handle (since years_of_operation was already defined as a number in the data structure Restaurant. So then MSON doesn't help eliminate the need to explicitly restate data structure definitions in this case?

zeluspudding commented 5 years ago

... So the benefit of using a data structure in this case is nill? I hope I'm not coming across as sour on this. I'm just genuinely trying to understand if there is a benefit to using a data structure in this case. API Blueprint is pretty awesome!

kylef commented 5 years ago

In a larger API, MSON gives you a way to reuse a data structure. Given perhaps a CRUD version of a restaurant API you could do something like the following:

# Restaurant API

## Restaurants Collection [/restaurants]

### List all restaurants [GET]

+ Response 200 (application/json)
    + Attributes (array[Restaurant], fixed-type)

### Create a Restaurant [POST]

+ Request (application/json)
    + Attributes (Restaurant)

+ Response 200 (application/json)
    + Attributes (Restaurant)

## Restaurant [/restaurants/{id}]

+ Parameters
    + id: 1 (number)

### View [GET]

+ Response 200 (application/json)
    + Attributes (Restaurant)

### Update [PATCH]

+ Request (application/json)
    + Attributes (Restaurant)

+ Response 200 (application/json)
    + Attributes (Restaurant)

### Delete [DELETE]

+ Response 204

# Data Structures

## Restaurant

+ `restaurant_name`: McDonald's (string, required) - The name of this restaurant
+ `years_of_operation`: 54 (number, required) - The number of years since established

In your particular use-case I agree with you that how MSON works doesn't quite work well for that particular case.

If you wanted to perhaps copy a real world response for an example over you could also do something like the following where I've included an actual JSON body alongside the attributes. As another option.

### List all restaurants [GET]

+ Response 200 (application/json)
    + Attributes (array[Restaurant], fixed-type)

    + Body

            [
                { "restaurant_name": "x", "years_of_operation": 5 },
                { "restaurant_name": "y", "years_of_operation": 6 },
                { "restaurant_name": "z", "years_of_operation": 5 }
            ]

In terms of rendering in Apiary documentation, it will then only keep 1 example which may be desired to keep the attributes section small and compact and just including the base structures (and not any larger examples):

screen shot 2018-09-14 at 23 23 03

While the JSON example, and the mock server would show the included example:

screen shot 2018-09-14 at 23 24 42

zeluspudding commented 5 years ago

Hmmm, that last half is helpful. Thank you so much Kyle!

RichardCullen commented 5 years ago

Looks like you have to declare the sample data for each member of the array; it doesn't give defaults:

### List all restaurants [GET /restaurants]

+ Response 200 (application/json)
    + Attributes
        + data (array)
            + (Restaurant)
              + restaurant_name: McDonald's
              + years_of_operation: 54
            + (Restaurant)
                + restaurant_name: Bob Evans
                + years_of_operation: 23
            + (Restaurant)
                + restaurant_name: Eataly
                + years_of_operation: 16