-
-
Save pithyless/0be222e1b1b3bca0239a9ca07d1b34c2 to your computer and use it in GitHub Desktop.
malli-meander.clj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns demo | |
(:require | |
[malli.core :as m] | |
[malli.transform :as mt] | |
[meander.epsilon :as meander])) | |
;; NOTE: Also important to mention I used m/validate m/parse etc., | |
;; but these should all be replaced with m/validator, m/parser etc. | |
;; in production code | |
(def source-shape | |
[:map | |
[:events [:sequential | |
[:map | |
[:id int?] | |
[:desc string?] | |
[:details-id int?]]]] | |
[:details [:sequential | |
[:map | |
[:id int?] | |
[:content string?]]]]]) | |
(def destination-shape | |
[:sequential | |
[:map | |
[:id int?] | |
[:description string?] | |
[:details string?]]]) | |
(defn custom-transform-logic | |
[data] | |
(-> data | |
(meander/search | |
{:events (meander/scan | |
{:id ?event-id | |
:desc ?description | |
:details-id ?details-id}) | |
:details (meander/scan | |
{:id ?details-id | |
:content ?details})} | |
{:id ?event-id | |
:description ?description | |
:details ?details}) | |
vec)) | |
(def sample-data | |
{:events [{:id "1" | |
:desc "Blah" | |
:details-id "11"} | |
{:id "2" | |
:desc "Blah 2" | |
:details-id "12"}] | |
:details [{:id "11" | |
:content "Blargh"} | |
{:id "12" | |
:content "Blargh 2"}]}) | |
;; Example broken input | |
(def sample-data2 | |
{:events [{:id nil | |
:desc "Blah" | |
:details-id 11}] | |
:details [{:id "11" | |
:content "Blargh"}]}) | |
(comment | |
(let [raw-data sample-data | |
;; First, normalize input (this is best-effort and does not throw errors). | |
;; This can take care of things like converting strings to integers, because | |
;; the serialization protocol could not represent integers, etc. | |
decoded (m/decode source-shape raw-data mt/string-transformer) | |
;; Second, validate that the normalized input matches our expectations. | |
;; NOTE: you can use m/validate instead of m/parse if schema has branching logic, | |
;; but you don't want to take advantage of the extra information at this point. | |
;; NOTE 2: you could use a different, more strict schema at this point. | |
parsed (m/parse source-shape decoded) | |
_ (when (identical? parsed ::m/invalid) | |
(throw (ex-info "Invalid Input" (m/explain source-shape decoded)))) | |
;; At this point we've validated input and want to do transformation | |
transformed (custom-transform-logic parsed) | |
;; And would be good idea to validate transformation worked... | |
_ (when-not (m/validate destination-shape transformed) | |
(throw (ex-info "Invalid Transformation" (m/explain destination-shape transformed))))] | |
transformed) | |
) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment