Search code examples
clojure

clojure string null check failed with string/blank


(defn get-coll-id [^String coll_id]
  (log/info "coll_id: " coll_id)
  (if (string/blank? coll_id)
    (let [collVal (get-coll-val)]
      (log/info "collVal: " collSeqVal)
      (format "C%011.0f" collVal))
    coll_id))

The log shows "coll_id: null". However, string/blank did not detect the null, and thus log of collVal is skipped. What is the method to check null string?


Solution

  • Something (perhaps a DB?) is giving you the string "null" for coll_id, or perhaps (log/info ...) converts a Clojure nil into the string "null".

    Consider this code:

    (ns tst.demo.core
      (:use tupelo.core tupelo.test)
      (:require
        [clojure.string :as str]
      ))
    
    (defn get-coll-id [^String coll_id]
      (println "coll_id: " coll_id)
      (if (str/blank? coll_id)
        (println :blank)
        coll_id))
    
    (dotest
      (newline)
      (println :v1)
      (spyx (get-coll-id nil))
    
      (newline)
      (println :v2)
      (spyx (get-coll-id (pr-str nil)))
    )
    

    with output:

    :v1
    coll_id:  nil
    :blank
    (get-coll-id nil) => nil
    
    :v2
    coll_id:  nil
    (get-coll-id (pr-str nil)) => "nil"
    

    No matter what you do, you get either the value nil or the string "nil" printed.

    Since I haven't used Java for a while, I tried to force it to generate the string "null", but calling o.toString() for a null value creates a NullPointerException, so that is not the answer.


    Update

    As amalloy points out, String.valueOf() will convert a Java null into the string "null":

    package demo;
    public class Demo {
      public static String go() {
        Object o = null;
        return String.valueOf( o );
      }
    }
    

    when run:

      (newline)
      (spyx :v3 (demo.Demo/go))
    

    with result

    :v3 (demo.Demo/go) => "null"
    

    As to your original question, the nil? function could be used:

    (defn blank-or-nil?
      [s]
      (or (nil? s)
        (str/blank? s)))
    
    (defn get-coll-id [^String coll_id]
      (println "coll_id: " coll_id)
      (if (blank-or-nil? coll_id)
        (println "found blank-or-nil coll_id")
        coll_id))
    

    which then prints found blank-or-nil coll_id when passed a nil value. However, this could confuse things if your are passed the string "null" or the string "nil".

    You need to clarify which value is the input, then track down the source.


    The above code is based on my favorite template project.