Whats the best way in kotlin for an null object's toString() method to return an empty string instead of "null"
Asked Answered
I

5

38

According to the official kotlin documentation, the toString() call of a null object returns "null" toString()

I want, that toString() should return an empty string ("") instead. I implemented it with an extension function.

fun Any?.toEmptyStringIfNull() :String {
if (this == null) {
    return ""
} else {
    return toString()
}

I am wondering if this could be achieved simpler/easier/cleaner and without calling the extension function everytime.

Iyeyasu answered 22/4, 2016 at 13:15 Comment(0)
F
60

How about:

nullable?.toString() ?: ""

or as Alexander Udalov suggested:

nullable?.toString().orEmpty()

Which one can wrap in an extension method:

fun Any?.toStringOrEmpty() = this?.toString() ?: ""
Favouritism answered 22/4, 2016 at 13:20 Comment(2)
Or a slightly more readable version: nullable?.toString().orEmpty()Peduncle
The implementation could probably be "${this ?: ""}", if you don't care about less performanceHermaphrodite
B
19

you can directly use nullable.orEmpty().

Reference: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/or-empty.html

Edit: Answer provided is incomplete - does only apply for String? and not Any? as pointed out in comment below.

Belch answered 14/8, 2019 at 15:38 Comment(3)
This is the better answer.Irinairis
orEmpty takes a String object, and the question is about converting Any? to String.Timisoara
@javaxian, thanks for pointing out. You are indeed correct. Will update my answer.Belch
B
1
nullable?.let {it.toString()}

If "nullable" is null it won't go further. As a variant. The only problem is that there will be a warning "redundant 'let' call could be removed.

Bourges answered 29/11, 2021 at 19:35 Comment(0)
C
0

I propose an extension function stringify, the name of which I borrowed from JavaScript's JSON.stringify().

fun <T> T?.stringify(toString: (T) -> String = { it.toString() }): String =
    if (this == null) "" else toString(this)

This covers the simple case and cases where you want to further process the string:

fun simplyConcatenate(s: String, postfix: String?): String = 
    s + postfix.stringify()

fun getFullTitle(title: String, disambiguation: String?): String = 
    title + disambiguation.stringify { " ($it)" }

fun demo() {
    println(simplyConcatenate("a", null)) // "a"
    println(simplyConcatenate("a", "b")) // "ab"
    println(getFullTitle("a", null)) // "a"
    println(getFullTitle("a", "b")) // "a (b)"
}

Edit: Now available in kotlin-lib.

Crenation answered 9/10, 2019 at 20:15 Comment(0)
C
0

The above answer not work for variable that is not original as String? because the toString() will directly transform a Any? to String (not to String?) if you write something like xxx.toString() ?: "" or xxx.toString().orEmpty() the IDE will tell you the right path will never be reach.

The solution is use "let" or "run". Depend on do you need to access outer scope class’ fun.

    Any? let { it.toString() } ?: ""
    Any? run { toString() } ?: ""

For example a fun we want a file name string from a nullable Path, or even a non-null path, its getFileName() may return null. And we want a empty string in that case instead of a "null" string.

    fun fileName(path: Path?): String = path?.fileName?.run { toString() } ?: ""

    fun removeExtension(path: Path?): String = path?.fileName?.let { removeExtension(it.toString()) } ?: ""
    fun removeExtension(fileName: String): String = FilenameUtils.removeExtension(fileName)

Commutative answered 8/2, 2021 at 16:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.