使用clj-http在Clojure中进行Post请求-无法接受请求正文?

4

我想要通过我的POST请求向CRM的API文档中发送JSON文件。

这个JSON文件是一个多层级的文件,在Clojure中被视为持久化数组映射。

我的发布代码如下:

(def contacts (http/post "https://api.close.com/api/v1/data/search" 
           {:basic-auth [api ""]
            :body closeFilter 
            })) 

CloseFilter代表我想要发布的多层JSON。

然而,我遇到了以下错误:

class clojure.lang.PersistentArrayMap cannot be cast to class [B (clojure.lang.PersistentArrayMap is in unnamed module of loader 'app'; [B is in module java.base of loader 'bootstrap')

这里我犯了什么错误?

更新

我正在重新创建一个我在JavaScript中拥有的程序。发布相同的文件可以完美地工作。

更新2-MRE

我仍然在努力解决这个问题,所以这里是我的代码示例。

我的代码首先需要我需要的包:

(ns schedule-emails.core
  (:require [clj-http.client :as http]
            [clojure.data.json :as json]
            [cheshire.core :refer :all]))

然后,我将本地JSON文件解析到应用程序中。这个JSON返回一个嵌套向量的映射。

(def closeFilter
  (json/read-str
   (slurp "URL TO LOCAL FILE")))

最后,我想将这些信息从本地文件发布到软件中:
def contacts (http/post "API URL HERE"
           {:accept :json
            :as :json
            :content-type :json
            :basic-auth [api ""]
            :body closeFilter}))

然而,我遇到了以下错误:
class clojure.lang.PersistentArrayMap 无法转换为类 [B (clojure.lang.PersistentArrayMap 在加载器“app”的未命名模块中;[B 在加载器“bootstrap”的 java.base 模块中)
我也尝试了下面建议的解决方案,但是我仍然遇到相同的问题。
3个回答

1

要使用内置的JSON强制转换请求体,您需要设置:form-params而不是:body,以及:content-type :json

;; Send form params as a json encoded body (POST or PUT)
(client/post "http://example.com" {:form-params {:foo "bar"} :content-type :json})

详情:https://github.com/dakrone/clj-http#post


1

clj-http 本身不会自动与某个后端协商并强制传输的数据"自动"转换。但是,您可以配置,在JSON的情况下,一些带有正确内容类型的数据将通过JSON从请求的主体转换为请求,并通过JSON从响应中返回数据。

  1. So you usually want the following things in the request:

    {:as :auto
     :coerce :always
     :content-type :application/json
     :body ...
     ; your own additional stuff...
     }
    

    So add a mime-type, so both clj-http knows what to do and the backend knows what it gets.

    See input coercion and output coercion

  2. and you have to make sure, that the means to make it actually working are there. This means, that you have added cheshire as dependency. See optional dependencies

当然,另一个选择是自己解决这个问题。因此,您需要添加一个库,该库可以从字符串或流创建JSON,并且需要设置content-type并转换主体/响应。


1
谢谢。我添加了 coerce 并添加了 :as :json 和内容类型。但是我仍然收到相同的错误。为了上下文,closeFilter 来自一个变量,该变量从文件系统读取 JSON 文件。 - Vinn
你添加了 Cheshire 吗? - cfrick
1
是的,我一开始就安装了 Cheshire。 - Vinn
那我建议您提供一个MRE - cfrick
1
嗨@cfrick - 我按照你的建议添加了一个MRE。我希望这能澄清我想做什么。 - Vinn

0
这个错误可能来自于clj-http/post,原因是closeFilter的类型既不是HttpEntity实例,也不是Java字节数组([B)或者java.lang.String。从3.12.3版本开始: https://github.com/dakrone/clj-http/blob/d92be158230e8094436f415324d96f2bd7cf95f7/src/clj_http/core.clj#L605C1-L611C54 接受的答案假设您想要自动进行类型转换。当使用clj-http时,我倾向于手动将JSON序列化为body值。
(client/post
 "http://example.com"
 {:content-type :json
  :body (-> form ch/generate-string})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接