Handle empty String as null
See original GitHub issueWhat is your use-case and why do you need this feature? Unfortunately, not every API sends valid JSON. Sometimes, it sends an empty string instead null. To use the nullable type, I use a workaround based on the private serialized string and typed getter/setter. A custom serializer for classes, containing many members, is more complex than this workaround.
It would be nice, if the serialization framework could handle this workaround, as a custom setting.
JsonConfiguration(handleEmptyStringAsNull = true
The default value should be false, to enforce strict mode.
Describe the solution you’d like
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import org.junit.Test
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNull
class EmptyStringSerializerTest {
private val json = Json(JsonConfiguration.Stable)
/**
* Normal, expected usage
*/
@Serializable
data class Valid(var content: Long?)
@Test
fun expected() {
val json = Json(JsonConfiguration(handleEmptyStringAsNull = true)) //TODO: New setting to convert empty strings to nullable, instead throwing, default = false (strict)
val invalideString = """{"content":""}"""
val failing = json.parse(Valid.serializer(), invalideString) // java.lang.NumberFormatException: For input string: ""
assertNull(failing.content)
}
/**
* Workaround to eliminate the usage of a custom serializer, which is not nice with a class containing many members
*/
@Serializable
data class Invalide(@SerialName("content") private var value: String) {
var content: Long? get() = value.toLongOrNull()
set(newValue) {
this.value = (newValue ?: "").toString()
}
}
/**
* Just testing the workaround
*/
@Test
fun customGetterSetterUsedByInvalide() {
val invalide = Invalide("foo")
invalide.content = null
val empty = json.stringify(Invalide.serializer(), invalide)
assertEquals("""{"content":""}""", empty)
val invalideParsed = json.parse(Invalide.serializer(), empty)
assertNull(invalideParsed.content)
invalide.content = 42
val contentString = json.stringify(Invalide.serializer(), invalide)
assertEquals("""{"content":"42"}""", contentString)
val contentSet = json.parse(Invalide.serializer(), contentString)
assertEquals(invalide, contentSet)
}
/**
* Working test of the valid, normal class
*/
@Test
fun valid() {
val valid = Valid(null)
val empty = json.stringify(Valid.serializer(), valid)
assertEquals("""{"content":null}""", empty)
val validParsed = json.parse(Valid.serializer(), empty)
assertNull(validParsed.content)
valid.content = 42
val contentLong = json.stringify(Valid.serializer(), valid)
assertEquals("""{"content":42}""", contentLong)
val contentSet = json.parse(Valid.serializer(), contentLong)
assertEquals(valid, contentSet)
}
}
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:14 (10 by maintainers)
Top Results From Across the Web
Get empty string when null - java
Returns either the passed in String, or if the String is null, an empty String (""). If you also want to get rid...
Read more >21.2 Validating Null and Empty Strings
An empty string is represented as "" . It is a character sequence of zero characters. A null string is represented by null...
Read more >Java: Check if String is Null, Empty or Blank
The isEmpty() method returns true or false depending on whether or not our string contains any text. It's easily chainable with a string...
Read more >When to Use NULL and When to Use Empty String
A string refers to a character's sequence. Sometimes strings can be empty or NULL. The difference is that NULL is used to refer...
Read more >Handle empty strings when migrating from Oracle to ...
However, because an empty string is another way of representing NULL in Oracle, no difference is observed when NULL handling functions are ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
The api sends
""
insteadnull
for every type, not onlyString
s. So your NullableStringSerializer has to be generic, which would be impossible…How to call this in
@Serializeable(with = NullableStringSerializer<In>::class)
?Another Problem is that e.g. the Discord API sometimes just returns an empty string as the entire response and currently there is no way of parsing that response properly as the
KSerializer
API doesn’t give you the information whether the input actually contains any content or not.The way we solved this before is just catching the error any decode method would throw when trying to decode an empty string, but this now causes the
lexer.expectEof()
line to fail after upgrading to 1.2.0