2013-03-04 24 views
7

Ich mache eine ziemlich einfache CRUD-Web-Service in Haskell mit Warp (und möglicherweise Scotty) und Säure-Zustand.Parsing json Objekte mit Aeson in Haskell

Im acid-state speichere ich Benutzerdatensätze in einer Data.Map (gemäß this Beispiel). Ich weiß, dass diese Aufzeichnungen bei der Erstellung immer komplett sein werden, also muss ich mich nicht mit einer Menge von MaybeS qualifizieren. Beim Aktualisieren eines Benutzers kann der Client jedoch ein Teil-JSON-Objekt senden, wobei nur einige der Felder ausgefüllt sind.

Was wäre der idiomatische Weg, dies darzustellen? Sollte ich eine Datendeklaration haben, FullUser, ohne MaybeS und genau dasselbe mit MaybeS vor allen optionalen Schlüsseln, PartialUser, und lasst Aeson automatisch für diese Kodierung und Dekodierung ableiten und schließlich eine eigene Updatefunktion vom Typ schreiben: Vollbenutzer -> PartialUser -> FullUser?

Es wäre nicht viel Code, aber es fühlt sich etwas hässlich an und es verletzt DRY ein bisschen. Es sollte eine so häufige Aufgabe in einem Webserver sein, vielleicht wurde es bereits generisch (möglicherweise mit TH) gelöst?

Ich merke, dass ich nur die JSON-Zeichenfolge speichern und immer nach fehlenden Schlüsseln suchen könnte. Das macht es etwas unhandlicher, aber zukunftssicherer für Schemaänderungen, aber ich würde trotzdem gerne wissen, wie ich es in einem "Typensafe" machen würde "Weise.

EDIT: Oder vielleicht sollte ich nur den FullUser haben und Aeson-Objektiv verwenden, um eine einfache Update-Funktion aus einem FullUser und einem JSON-String zu schreiben?

Antwort

7

Idiomatic Haskell macht so viel statische Überprüfung wie möglich. Sie sollten Ihr Problem immer aus einer Perspektive betrachten, ob es möglich ist, dynamische Prüfungen durch statische zu ersetzen. Das ist im Wesentlichen das, was die folgende Aussage über Haskell der Realität ziemlich nahe bringt: "Wenn es kompiliert, funktioniert es". Also definitiv ein "Nein" zum Arbeiten mit Plain JSON.

Ihre Lösung mit FullUser und PartialUser ist korrekt. Obwohl ich vorschlagen würde, einen anderen Namen Ansatz zu nehmen: User und UserJSON - auf diese Weise erhalten Sie eine ziemlich beschreibende und sinnvolle Bedeutung.

Es gibt jedoch ein kleines Problem mit Aeson: die generierten Instanzen don't yet support parsing missing fields (bitte abstimmen). Also müssen Sie die Instanzen manuell definieren.

+0

Vielen Dank für Ihre Eingabe! Ja, die Namensgebung war nur um die Frage klarer zu machen. Da generierte Instanzen in diesem Fall nicht ausreichen werden, denke ich, werde ich mit einer Update-Funktion gehen, die einen FullUser- und einen JSON-String verwendet und ein Aeson-Objektiv (und vielleicht ein Objektiv für FullUser) verwendet, um es zu aktualisieren. – Gurgeh