How can I update and iterate the sub maps and update map into different location of map at the same time in clojure

79 views Asked by At

I've below clojure object.

{:openapi "3.0.3",
 :info {:title "Swagger API", :version "0.0.1"},
 :paths
 {"/api"
  {:post
   {:parameters
    [{:in "query",
      :name "x",
      :description "",
      :required true,
      :schema {:type "integer", :format "int64"}}
     {:in "query",
      :name "y",
      :description "",
      :required true,
      :schema {:type "integer", :format "int64"}}
     {:in "header",
      :name "Content-Type",
      :description "",
      :required true,
      :schema
      {:type "string",
       :enum ["application/json" "application/xml" "application/edn"]}}
     {:in "header",
      :name "Accept",
      :description "",
      :required true,
      :schema {:type "string"}}],
    :requestBody
    {:content
     {:application/json
      {:schema {:$ref "#/components/schemas/Body15899"}}}},
    :responses
    {:200
     {:description "ok",
      :content
      {:application/json
       {:schema {:$ref "#/components/schemas/Tag"}}}},
     :400
     {:description "ok",
      :content
      {:application/json
       {:schema {:$ref "#/components/schemas/FatalError"}}}}}}}},
 :components
 {:schemas
  {:Body15899
   {:type "object",
    :properties {:foo {:type "string"}},
    :additionalProperties false,
    :required ["foo"]},
   :FatalError
   {:type "object",
    :properties
    {:id {:type "string"},
     :description {:type "string"},
     :code {:type "string"}},
    :additionalProperties false,
    :required ["id" "description" "code"]},
   :Tag
   {:type "object",
    :properties
    {:id
     {:description "Unique identifier for the tag",
      :type "integer",
      :format "int64"},
     :name {:description "Friendly name for the tag"}},
    :additionalProperties false}}}}

I need to move [:paths :requestBody] to [:components :requestBodies] and [:paths :responses ] to [:components responses]0.0.1 When I do that I need to other objects [:paths :parameters] intact. I need to do this for all endpoints. like so the above the object should result into below -

{:openapi "3.0.3",
 :info {:title "Swagger API", :version "0.0.1"},
 :paths
 {"/api"
  {:post
   {:parameters
    [{:in "query",
      :name "x",
      :description "",
      :required true,
      :schema {:type "integer", :format "int64"}}
     {:in "query",
      :name "y",
      :description "",
      :required true,
      :schema {:type "integer", :format "int64"}}
     {:in "header",
      :name "Content-Type",
      :description "",
      :required true,
      :schema
      {:type "string",
       :enum ["application/json" "application/xml" "application/edn"]}}
     {:in "header",
      :name "Accept",
      :description "",
      :required true,
      :schema {:type "string"}}],
    :requestBody
    {:$ref "#/components/responses/Tag"},
    :responses
    {200
     {:$ref "#/components/responses/Tag"},
     400
     {:$ref "#/components/responses/FatalError"}}}}},
 :components
 {:schemas
  {"Body15830"
   {:type "object",
    :properties {:foo {:type "string"}},
    :additionalProperties false,
    :required [:foo]},
   "FatalError"
   {:type "object",
    :properties
    {:id {:type "string"},
     :description {:type "string"},
     :code {:type "string"}},
    :additionalProperties false,
    :required [:id :description :code]},
   "Tag"
   {:type "object",
    :properties
    {:id
     {:description "Unique identifier for the tag",
      :type "integer",
      :format "int64"},
     :name {:description "Friendly name for the tag"}},
    :additionalProperties false}}}
   :responses 
   {"Tag"
    {:description "ok",
     :content
     {"application/json"
      {:schema {:$ref "#/components/schemas/Tag"}}}}
    "FatalError"
    {:description "ok",
     :content
     {"application/json"
      {:schema {:$ref "#/components/schemas/FatalError"}}}}}
   :requestBodies
   {"Body15830"
    {:content
     {"application/json"
      {:name "Body15830",
       :schema {:$ref "#/components/schemas/Body15830"}}}}}
    }

Below is the clojure code I wrote.

(defn get-response-ref [v]
  (some-> (-> v
              :content
              vals
              first
              :schema
              :$ref)
          (str/replace "/schemas/" "/responses/")))

(defn endpoint-processor2 [endpoint]
  (let [backup (reduce-kv (fn [acc method definition]
                            (let [body-acc      (if (:requestBody definition)
                                                  (-> acc
                                                      (update-in [:requestBodySchemas] conj (:requestBody definition))
                                                      (update-in [:requestBodyDefinitions method] conj (str "#components/requestBodies/" (-> (get-in definition [:requestBody :content])
                                                                                                                                             vals
                                                                                                                                             first
                                                                                                                                             :name)))) acc)
                                  responses-acc (reduce-kv (fn [acc-res k v]
                                                             (clojure.pprint/pprint v)
                                                             (-> acc-res
                                                                 (update-in [:responses method k] conj (get-response-ref v))
                                                                 (update-in [:responses-schema] conj v))) body-acc (:responses definition))]
                              responses-acc))
                          {} endpoint)]
    backup))

when I call the above code with (endpoint-processor2 (get-in oa [:paths "/api"])) I get below response ->


(def oa {:openapi "3.0.3",
         :info {:title "Swagger API", :version "0.0.1"},
         :paths
         {"/api"
          {:post
           {:parameters
            [{:in "query",
              :name "x",
              :description "",
              :required true,
              :schema {:type "integer", :format "int64"}}
             {:in "query",
              :name "y",
              :description "",
              :required true,
              :schema {:type "integer", :format "int64"}}
             {:in "header",
              :name "Content-Type",
              :description "",
              :required true,
              :schema
              {:type "string",
               :enum ["application/json" "application/xml" "application/edn"]}}
             {:in "header",
              :name "Accept",
              :description "",
              :required true,
              :schema {:type "string"}}],
            :requestBody
            {:content
             {:application/json
              {:schema {:$ref "#/components/schemas/Body15899"}}}},
            :responses
            {:200
             {:description "ok",
              :content
              {:application/json
               {:schema {:$ref "#/components/schemas/Tag"}}}},
             :400
             {:description "ok",
              :content
              {:application/json
               {:schema {:$ref "#/components/schemas/FatalError"}}}}}}}},
         :components
         {:schemas
          {:Body15899
           {:type "object",
            :properties {:foo {:type "string"}},
            :additionalProperties false,
            :required ["foo"]},
           :FatalError
           {:type "object",
            :properties
            {:id {:type "string"},
             :description {:type "string"},
             :code {:type "string"}},
            :additionalProperties false,
            :required ["id" "description" "code"]},
           :Tag
           {:type "object",
            :properties
            {:id
             {:description "Unique identifier for the tag",
              :type "integer",
              :format "int64"},
             :name {:description "Friendly name for the tag"}},
            :additionalProperties false}}}})

(endpoint-processor2 (get-in ao [:paths "/api"]))

I get below response -

{:requestBodySchemas ({:content {:application/json {:schema {:$ref "#/components/schemas/Body15899"}}}}),
 :requestBodyDefinitions {:post ("#components/requestBodies/")},
 :responses {:post {:200 ("#/components/responses/Tag"), :400 ("#/components/responses/FatalError")}},
 :responses-schema ({:description "ok",
                     :content {:application/json {:schema {:$ref "#/components/schemas/FatalError"}}}}
                    {:description "ok", :content {:application/json {:schema {:$ref "#/components/schemas/Tag"}}}})}

I don't know how can I merge accordingly in the respective $ref component locations. I'm new to clojure. How can I achieve the same.

0

There are 0 answers