Closed onetom closed 2 years ago
Unfortunately, this is failing with some strange validation errors at the moment:
(martian/request-for xero-api :get-report-profit-and-loss)
Execution error (ExceptionInfo) at schema-tools.coerce/coerce-or-error! (coerce.cljc:24).
Could not coerce value to schema: {:xero-tenant-id disallowed-key}
(martian/request-for xero-api :get-report-profit-and-loss
{:xero-tenant-id "<tenant id override>"})
Execution error (ExceptionInfo) at schema-tools.coerce/coerce-or-error! (coerce.cljc:24).
Could not coerce value to schema: {:xero-tenant-id disallowed-key}
I have the suspicion that the source of the error is caused by some of the changes between v0.1.16 and
master` and not by my patches.
Either way, we have decided to resolve the $refs and inline the path-level params in the openapi format, before passing it into martian and that worked.
Here is the rough summary of our approach:
(ns xero.repl
(:require
[clojure.data.json :as json]
[clojure.string :as str]
[martian.core :as martian]
[martian.openapi :as openapi]
[martian.interceptors :as interceptors]
[martian.clj-http :as martian-http]))
(defn map-vals
"{:a 1
:b 2}
->
{:a (f 1)
:b (f 2)}"
[f m] (reduce-kv #(assoc %1 %2 (f %3)) {} m))
(defn json-decode
"Blank strings are decoded as nil."
[json-str & args]
(if (str/blank? json-str)
nil
(apply json/read-str json-str :key-fn keyword args)))
;; Get Xero OpenAPI in JSON format:
;; curl -s https://raw.githubusercontent.com/XeroAPI/Xero-OpenAPI/master/xero_accounting.yaml | yaml2json > xero_accounting.json
(defn select-paths [openapi paths]
(update openapi :paths select-keys (map keyword paths)))
(def xero-openapi
(-> (json-decode (slurp "xero_accounting.json"))
(select-paths ["/Reports/ProfitAndLoss"])))
(defn de$ref
"Can use with clojure.walk/postwalk to substitute JSON references with
their values.
Documentation about JSON references:
https://tools.ietf.org/id/draft-pbryan-zyp-json-ref-03.html"
[components x]
(if-let [ref (and (map? x) (:$ref x))]
(#'openapi/lookup-ref components ref)
x))
(defn preprocess-params
"Inject path-level parameters into the operation-level parameter lists and
resolve parameter references."
[openapi]
(let [de$ref-params (partial map (partial de$ref (:components openapi)))]
(update openapi :paths
(partial map-vals
(fn [ops]
;; ops is a map. Its keys are keywordized HTTP method
;; names OR :parameters or :description
(let [+route-params (partial into (:parameters ops))]
(->> ops
(map-vals
(fn [op]
(cond-> op
(:operationId op)
(update :parameters
(comp
de$ref-params
+route-params))))))))))))
(defn xero-api []
(martian/bootstrap-openapi
(openapi/base-url xero-openapi)
(preprocess-params xero-openapi)))
(comment
(martian/request-for xero-api :get-report-profit-and-loss
{:xero-tenant-id "<tenant id override>"})
)
What's your opinion @oliyh ?
Here is a version of the preprocessing with Specter:
(defn preprocess-params-with-specter [openapi]
(->> openapi
(transform
[(collect-one :components)
:paths MAP-VALS
(collect-one :parameters)
MAP-VALS #(:operationId %) :parameters]
(fn [components path-params method-params]
(->> (into path-params method-params)
(map (partial de$ref components)))))))
Hello,
Thank you for all your efforts here. I haven't had time to look properly at your code yet but it should be possible for martian to understand this natively without you needing to preprocess anything.
I'll try to find time to look into this for you.
Having the same issue, and it would be cool to have it solved
Hello,
I used some of your code to implement this in #140, thank you. It's now available in 0.1.21-SNAPSHOT
, so closing this PR.
Support parameter refs
Support route-level parameters (including parameter refs)