DE EN

Fortgeschrittenes Blueprint mit MSON.

von

Im vorhergehenden Blogpost “API specs mit Apiary und Blueprint” habe ich erklärt, wie man eine erste API mit einfachen Blueprint Elementen definieren kann.

In diesem Beitrag möchte ich zeigen, wie man von den zahlreichen JSON Beispielen in der Spezifikation Abschied nehmen kann. Wenn die API wächst, kommt man nämlich ziemlich schnell zu dem Punkt an dem man JSON copy/pasted, und das wird dann ein Problem.

MSON benutzen

Denn wie wir alle wissen:

CTRL-X, CTRL-C, CTRL-V ist die Achse des Bösen.

  • Grantiger Grobmeier, auf irgendeiner Trainings-Session (möglicherweise hat das auch wer anderes gesagt, aber ich denke, ich war der Erste!)

Sehen wir mal, was wir bisher haben:

+ Response 200 (application/json)

          {
            "id": 1235,
            "name": "Christian",
            "surname": "Grobmeier"
          }

JSON ist durchaus lesbar, aber es wäre natürlich schön wenn wir beispielsweise auch dokumentieren könnten was optional und was erforderlich ist. Auch können wir keine Datentypen vergeben oder überhaupt diesem Objekt einen Namen.

Das ist genau der Zeitpunkt, an dem MSON ins Spiel kommt. MSON bedeutet “Markdown Syntax for Object Notation”, ist also eine “Markdown Schreibweise um Objekte zu beschreiben”. Wie der Name schon andeutet ist MSON Kompatibel zu JSON und zielt darauf ab, eben jenes zu erweitern.

In der Apiary API Spezifikation müssen wir also eine neuen Abschnitt einfügen, den wir “Data Structures” nennen. Ich bevorzuge das Ende Dokuments dafür, ähnlich einem Anhang.

Dann kann man bereits mit der Definition beginnen. Es sieht etwa so aus.

# Data Structures

## Person (object)

- id: 123 (number)
- name: Christian (string, required)
- surname: Grobmeier (string, required)

In der zweiten Überschrift sieht man nach dem Objekt-Namen den Typen des Objekts “Object”, welcher sich auf den JSON Typ “Object” bezieht.

Es folgt eine Liste von Objekt-Eigenschaften mitsamt deren Typ-Definitionen, die wir bereits vom letzten Blog-Post her kennen.

Benutzen wir das Konstrukt:

## Person Collection [/persons]

### Get all persons [GET]

+ Response 200 (application/json)
    + Attributes
        - data (array[Person])

Ich habe eine neue Action in der Collections “/persons” eingeführt, die alle Personen die wir gespeichert haben zurückgeben soll. Hoffentlich sind das nicht zu viele! ;-)

Im Rückgabe-Type habe eine Liste mit dem Namen “Attributes” angelegt. Es stellt sich dann im Editor als ein Objekt dar, das ein Feld mit dem Namen “data” hat, das wiederrum ein Array von Personen beinhaltet.

In Apiary sieht das dann folgendermaßen aus:

Apiary

Das ist schon zeimlich schön. Und natürlich kann man MSON in den Anfragen auch verwenden. Mit diesem Feature, können wir Objekte wieverwenden und unsere Dokumentation aktualisiert sich, wenn wir irgendwas in der Datenstruktur verändert haben.

Multiple Antworttypen

Manchmal ist es notwendig, die Bedeutung eines bestimmten Parameters genau zu erläutern und beispielhaft darzustellen.

Sehen wir uns das Beispiel im vorhergehenden Post an, in dem wir eine Action wie diese hier benutzten:

### Get a person [GET /persons/{id}{?include}]

In Wirklichkeit könnte das jemand so aufrufen: /persons/123?include=metadata und das Ergebnis würde (hoffnetlich) auch die Metadaten enthalten. Aber wie können wir das dokumentieren?

Es ist tatsächlich sogar recht einfach. Solange wir unsere Anfrage-Abschnitte anständig benennen, können wir auch mehrere haben. Das könnte so aussehen:

### Get a person [GET /persons/{id}{?include}]

+ Parameters
    + id: 123 (string, required)
    + include: metadata (string, optional)
        + Members
            + metadata
        + Default: metadata

+ Response 200 (application/json)

    + Attributes (Person)

+ Request with metadata (application/json)

+ Response 200 (application/json)

    + Attributes (PersonWithMetadata)

Den Teil mit den Parametern kennen wir ja schon. Die erste Anfrage ist implizit, falls es nichts weiter gibt. Dann habe ich eine zweite Anfrage angelegt, die ich “with metadata” genannt habe.

Die Antwort kann dann unterschiedlich sein. Man könnte also verschiedene MSON Objekte verwenden.

“Ableiten” von anderen MSON Definitionen

Im obigen Fall bräuchte man dann unglücklicherweise ein vollständig anderes Model, und das ist recht unangenehm. Eine Menge Objekteigenschaften bleiben ja gleich, und das alles synchron zu halten schreit geradezu nach Bugs.

Glücklicherweise können wir aber die Felder des Original-Models einfügen.

Das sieht so aus:

# Data Structures

## Person (object)

- id: 123 (number)
- name: Christian (string, required)
- surname: Grobmeier (string, required)

## PersonWithMetaData (object)

- Include Person
- meta (object)
    - created: 2015
    - editor: 1234

Die “Include” Anweisung hilft. Nun haben wir zwei verschiedene Objekte, aber es bleibt einigermaßen leicht zu pflegen.

Zusammenfassung

MSON ist ziemlich nett, wenn man in seiner API mit Objekten arbeiten muss, aber auch nicht perfekt. Es gibt einige Stellen, die heftiges Stirnrunzlen verursachen können. Aber für 95% der Fälle sollte MSON eine anständige Lösung sein.

Ableitung ist elementar, wenn das Projekt wächst, und man sollte die Möglichkeit mit den Datenstrukturen ausführlich nutzen.

Die Apiary Dokumentation ist online.

Und der Source Code ist auf GitHub.

Bildrechte

Tags: #apiary #blueprint #rest #specification #documentation

Newsletter

ABMELDEN