首页 > 解决方案 > Clojure:解析 json 并提取值

问题描述

我正在调用 API 并使用 Cheshire 解析 JSON:

(defn fetch_headlines [source]
  (let [articlesUrl (str "https://newsapi.org/v2/top-headlines?sources=" 
                         source
                         "&apiKey=a688e6494c444902b1fc9cb93c61d6987")]
    (-> articlesUrl
        client/get
        generate-string 
        parse-string)))

JSON 有效负载:

{"status" 200, "headers" {"access-control-allow-headers" "x-api-key, 授权", "content-type" "application/json; charset=utf-8", "access-control -allow-origin" "*", "content-length" "7434", "connection" "close", "pragma" "no-cache", "expires" "-1", "access-control-allow-methods " "GET", "date" "Thu, 28 Mar 2019 20:22:16 GMT", "x-cached-result" "false", "cache-control" "no-cache"}, "body" "{ \"status\":\"ok\",\"totalResults\":10,\"articles\":[{\"source\":{\"id\":\"cnn\",\"name \":\"CNN\"},\"author\":null,\"title\":\"Trump: Mueller probe was 'attempted takeover' of government - CNN Video\",\"description\":\"福克斯新闻采访肖恩·汉尼提,特朗普总统称特别顾问罗伯特·穆勒的调查是“企图接管我们的政府”。\\"\",\"url\":\"http://us.cnn.com/videos/politics/2019/03/28/trump-mueller-probe-attempted-takeover-hannity-cpt-sot-vpx.cnn \",\"urlToImage\":\" https://cdn.cnn.com/cnnnext/dam/assets/190324191527-06-trump-mueller-reaction-0324-super-tease.jpg\",\"publishedAt\":\"2019-03-28T20:09:04.1891948Z\",\"content\":\"在 Facebook Messenger 中与我们聊天。了解世界正在发生的事情。\"},{\"source\":{\"id\":\"cnn\",\"name\":\"CNN\"},\" author\":null,\"title\":\"James Clapper 回应称他应该被调查 - CNN 视频\",\"description\":\"前国家情报总监 James Clapper 回应白宫新闻秘书莎拉桑德斯说,在特别顾问罗伯特穆勒没有建立特朗普之间的勾结之后,应该调查他和其他前情报官员……\",\"url\":\" http://us.cnn。https://cdn.cnn.com/cnnnext/dam/assets/190325211210-james-clapper-ac360-03252019-super-tease.jpg \",\"publishedAt\":\"2019-03-28T20:08: 43.1736236Z\",\"content\":\"在 Facebook Messenger 中与我们聊天。了解世界正在发生的事情。\"},{\"source\":{\"id\":\"cnn\",\"name\":\"CNN\"},\" author\":\"Maegan Vazquez, CNN\",\"title\":\"特朗普将在穆勒调查结束后首次集会\",\"description\":\"唐纳德·特朗普总统首次亮相自罗伯特·穆勒结束调查以来,支持者们将于周四晚上在密歇根州大急流城的一次集会上发表讲话。\",\"url\":\" http://us.https://cdn.cnn.com/cnnnext/dam/assets/190321115403-07-donald-trump-lead-image-super-tease.jpg\",\"publishedAt\":\"2019-03-28T19:49:26Z\",\"content\":\"华盛顿 (CNN) 总统唐纳德·特朗普自罗伯特·穆勒 (Robert Mueller) 结束他的任期以来首次出现在支持者面前调查,定于星期四晚上在密歇根州大急流城的一次集会上发表讲话。\r\n这次集会是在华盛顿混乱的一周之后进行的,具体... [+2099 chars]\"},{\"source\":{\" id\":\"cnn\",\"name\":\"CNN\"},\"author\":\"Katelyn Polantz, CNN\",\"title\":\"法官命令司法部. to turn over Comey memos\",\"description\":\"一名联邦法官下令将 James Comey 的备忘录交出,在美国有线电视新闻网和其他媒体组织提起的诉讼案件中,要求查阅纪念前联邦调查局局长与唐纳德特朗普总统互动的文件。\",\"url\":\"http ://us.cnn.com/2019/03/28/politics/james-comey-memo-lawsuit/index.html\",\"urlToImage\":\" https://cdn.cnn.com/ cnnnext/dam/assets/181209143047-comey-1207-super-tease.jpg\",\"publishedAt\":\"2019-03-28T19:14:45Z\",\"content\":\"华盛顿(CNN)一名联邦法官下令司法部和联邦调查局提交詹姆斯·科米的备忘录在美国有线电视新闻网和其他媒体组织提起的诉讼案件中,为了查阅纪念前 FBI d 的文件,将其全部密封交给法庭... [+1043 chars]\"},{\"source\":{\"id \":\"cnn\",\"name\":\"CNN\"},\"author\":\"Clare Foran and Manu Raju, CNN\",\"title\":\"佩洛西致电AG 对穆勒报告“傲慢”的总结\"、\"描述\":\"众议院议长南希·佩洛西周四批评了司法部长威廉·巴尔对特别顾问罗伯特·穆勒报告的总结,称它为 \\"居高临下\\" 和 \\"傲慢\\" 并说 \\"这不是正确的做法。\\"\",\"url\":\"小狗般的支持总统。特朗普喜欢奖励与他相处融洽的人,这将我们带到了 45 分钟的 ph...\",\"url\":\"http://us.cnn.com/2019/03/28/politics/sean-hannity-donald-trump-mueller/index.html \",\"urlToImage\":\" https://cdn.cnn. com/cnnnext/dam/assets/190328140149-01-hannity-trump-file-super-tease.jpg\",\"publishedAt\":\"2019-03-28T18:44:21Z\",\"content\":\"(CNN)唐纳德·特朗普总统最喜欢的“记者”福克斯新闻的肖恩·汉尼提——主要是因为汉尼提坚定不移地支持总统,就像小狗一样。特朗普喜欢奖励与他相处融洽的人,这将我们带到了 45 分钟... [+14785 字符]\"},{\"source\":{\"id\":\"cnn\",\ "name\":\"CNN\"},\"author\":null,\"title\":\"Puerto Rico Gov.:我要揍那个恶霸的嘴 - CNN Video\",\"描述\":\"波多黎各总督里卡多·罗塞洛在接受CNN独家采访时表示,他不会坐视其官员被白宫欺负。\",https://cdn.cnn.com/cnnnext/dam/assets/190328123504-puerto-rico-gov-ricardo-rosello-super-tease.jpg \",\"publishedAt\":\"2019-03-28T18: 08:33.7312458Z\",\"content\":\"在 Facebook Messenger 中与我们聊天。了解世界正在发生的事情。\"},{\"source\":{\"id\":\"cnn\",\"name\":\"CNN\"},\" author\":\"Jeremy Herb, Manu Raju 和 Ted Barrett, CNN\",\"title\":\"Jared Kushner 接受参议院情报委员会采访\",\"description\":\"唐纳德特朗普总统的儿子-作为委员会俄罗斯调查的一部分,姻亲贾里德库什纳周四返回参议院情报委员会进行闭门采访。\",\"url\":https://cdn.cnn.com/cnnnext/dam/assets/180302124221-30-jared-kushner-super-tease.jpg \",\"publishedAt\":\"2019-03-28T16:21:29Z\ ",\"content\":null},{\"source\":{\"id\":\"cnn\",\"name\":\"CNN\"},\"author\": \"Jeremy Herb 和 Laura Jarrett, CNN\",\"title\":\"Mueller 的报告超过 300 页,消息人士称\",\"description\":\"特别顾问 Robert Mueller 关于俄罗斯调查的机密报告据司法部一名官员和另一位知情人士透露,该文件超过 300 页。\",\"url\":\" http://us.cnn.com/2019/03/28/politics /mueller-report-pages/index.html \",\"urlToImage\":\"https://cdn.cnn.com/cnnnext/dam/assets/190324130054-05-russia-investigation-0324-super-tease.jpg\",\"publishedAt\":\"2019-03-28T15:52:01Z\",\"content\":null},{\"source\":{\"id\":\"cnn\ ",\"name\":\"CNN\"},\"author\":\"Jim Acosta and Kevin Liptak, CNN\",\"title\":\"独家:波多黎各州长警告白宫资金\",\"说明\":\"唐纳德特朗普总统和波多黎各州长之间的紧张局势正在升级,因为在飓风玛丽亚之后,这个仍然遭受重创的岛屿的救灾工作进展缓慢。\",\"url\ ":\" http://us.cnn.com/2019/03/28/politics/ricardo-rossell-donald-trump-puerto-rico-funding/index.html \",\"urlToImage\":\" https://cdn.cnn。com/cnnnext/dam/assets/180920230539-pr-storm-of-controversy-rossello-trump-super-tease.jpg \",\"publishedAt\":\"2019-03-28T15:19:39Z\", \"content\":null}]}", "跟踪重定向" ["https://newsapi.org/v2/top-headlines?sources=cnn&apiKey=a688e6494c444902b1fc9cb93c61d687 "]}

我想提取以从返回的 JSON 有效负载中提取 URL,我试过这个:

(defn fetch_headlines [source]
  (let [articlesUrl (str "https://newsapi.org/v2/top-headlines?sources="
                         source
                         "&apiKey=a688e6494c444902b1fc9cb93c61d697")]
    (-> articlesUrl
        client/get
        generate-string 
        parse-string
        (get-in ["source" "url"]))))

但我得到了一个nil结果,有什么想法吗?

基于用户反馈的解决方案:

(defn fetch-headlines [source]
  (let [articlesUrl (str "https://newsapi.org/v2/top-headlines?sources=" 
                         source
                         "&apiKey=a688e6494c444902b1fc9cb93c61d697")]
    (-> articlesUrl
        client/get
        :body
        parse-string
        (get-in ["articles" 0 "url"]))))

标签: jsonclojure

解决方案


您需要的是body键内部,但与该键对应的值仍然是字符串,还不是 clojure 映射。当您查找时source,您会nil返回,因为该键不存在(它应该在里面body,在将字符串正确解析为 json 之后)。

一旦你正确解析了这个body值,它应该是这样的:

(let [index-of-article 0]
  (get-in response ["body" "articles" index-of-article "url"]))

whereindex-of-article是您想要的文章的位置索引,因为文章包含文章向量。


推荐阅读