clojureclojure-java-interop

Add object to a list in clojure and return


I am new to functional programming and have a use case where I have a list of Books, I want to iterate over it, do some mapping and return a new List. My code

(defn map-book [books]
  ((doseq [x books]
     (let [lst (create-response x)]
       (println "data -> " (json/encode lst))
       (json/encode lst)))))
    

(defn create-response [book]
  (let [updated-book (merge {"book-name" (.getBookName book)
                             "book-page"   (.getBookPageCount book)}]
  updated-book))

when I try to run this, I am able to get json decoded response in terminal due to println but not the json list as a response from the function. have been stucked around for some time on this.

What I want is something like :

[{
        "book-name": "rick boy",
        "book-page": 110

    },
    {
        "book-name": "poor boy",
        "book-page": 124
    }
]

but am getting something like, when I run my unit test:

#object[book_service.book$map_book 0x7915bca3 [book_service.book$map_book@7915bca3]

thanks for any help!


Solution

  • If you want to return new list (or vector), you should avoid doseq (which is for side effects- for example, printing, and always returns nil) and use map or for instead.

    I guess you want to return JSON string for given data and your json library is actually Cheshire:

    Dependencies: [cheshire "5.11.0"]

    Require in ns: [cheshire.core :as json]

    Book class:

    public class Book {
        String bookName;
        Long pageCount;
    
        public Book(String name, Long pages) {
            bookName = name;
            pageCount = pages;
        }
    
        public String getBookName() {
            return bookName;
        }
    
        public Long getBookPageCount() {
            return pageCount;
        }
    }
    

    Clojure code:

    (defn get-book-map [book]
      {"book-name" (.getBookName book)
       "book-page" (.getBookPageCount book)})
    
    (defn encode-books [books]
      (json/encode (map get-book-map books)))
    

    Test:

    (encode-books [(Book. "rick boy" 110)
                   (Book. "poor boy" 124)])
    => "[{\"book-name\":\"rick boy\",\"book-page\":110},{\"book-name\":\"poor boy\",\"book-page\":124}]"
    
    (json/decode *1)
    => ({"book-name" "rick boy", "book-page" 110} {"book-name" "poor boy", "book-page" 124})