Search code examples
jsonclojurescriptclj-http

Clojurescript error with cljs-http GET request for JSON file - badly formed


Beginner Clojurist here. I'm trying to parse a JSON file using Clojurescript and the cljs-http library. I have strange behaviour using the following function:

(defn make-remote-call [endpoint]
  (go (let [response (<! (http/get endpoint))]
    (js/console.log (:body response)))))

This will print the json file to the console but I'll get this error message:

XML Parsing Error: not well-formed
Location: file:///***U2328710-data.json
Line Number 1, Column 1: 

Things I've tried:

  • the JSON file passes http://jsonlint.com with success, but https://jsonformatter.curiousconcept.com/ parses the file and says Error:Invalid encoding, expecting UTF-8, UTF-16 or UTF-32.[Code 29, Structure 0]
  • same issue when I deploy on Apache server. My .htaccess file is correctly set up to send content-header to application/json and charset to utf-8 (though I've read I should be sending UTF-8 in caps, haven't been able to do that)
  • I can parse an XML file with the same function without a problem
  • I can parse the same JSON file without a problem using the deprecated js/XMLHttpRequest

Running out of ideas - can someone help please? I wonder if cljs-http doesn't understand it's a json file, can I force it / maybe override headers? Thanks,


Solution

  • I think it's either some encoding problem in your JSON file or some other problem outside of the cljs-http library. I ran a small test using a new project created with lein new figwheel json-client and added the dependency on [cljs-http "0.1.46"] to project.clj

    For a valid JSON file, I went to https://api.github.com/users/clojure/repos and saved the contents as resources/public/repos.json inside the project folder.

    The contents of my core.clj file are:

    (ns json-client.core
      (:require-macros [cljs.core.async.macros :refer [go]])
      (:require [cljs-http.client :as http]
                [cljs.core.async :refer [<!]]))
    
    (enable-console-print!)
    
    (defn make-remote-call [endpoint]
      (go (let [response (<! (http/get endpoint))]
            (js/console.log (clj->js (:body response)))))) ;; NOTE: cljs->js
    
    (defonce app-state (atom {:text "Hello world!"}))
    
    ;; This content is served by figwheel, configured in project.clj
    (make-remote-call "http://0.0.0.0:3449/repos.json")
    
    (defn on-js-reload []
      ;; optionally touch your app-state to force rerendering depending on
      ;; your application
      ;; (swap! app-state update-in [:__figwheel_counter] inc)
    )
    

    Note: there's only one change in the line that logs to the console (uses clj->js) but that's all.

    ... when I launch the project with lein figwheel it takes a few seconds and launches a new browser tab with the project and on the console I can see it logging the contents of the JSON file:

    enter image description here