breezymri
breezymri

Reputation: 4353

Idiomatic way of branching json parsing in kotlin

Let's say that we have a JsonNode object jsonNodeObj that needs to be parsed to one of multiple classes ClassA, ClassB, ClassC, etc. I could do the following (couldn't be more ugly):

val mapper = ObjectMapper()
try {
  mapper.treeToValue(jsonNodeObj, ClassA::class.java)
} catch (e1: Exception) {
  try {
    mapper.treeToValue(jsonNodeObj, ClassB::class.java)
  } catch (e2: Exception) {
    try {
      mapper.treeToValue(jsonNodeObj, ClassC::class.java)
    } catch (e3: Exception) {
      ...
    }
  }
}

Is there a better way like using when somehow?

Upvotes: 3

Views: 157

Answers (1)

msrd0
msrd0

Reputation: 8390

There is definitely a better way to do this. You can define a function that returns true on success and false on exception like so:

inline fun <reified T : Any> ObjectMapper.treeToValueOrNull<T>(node : TreeNode) : T?
    = try { treeToValue(node, T::class.java) }
    catch (ex : Exception) { null }

This works because in Kotlin try-catch-statements can have a return value. Now, you can use when to process the json:

lateinit var object : Any
when {
    mapper.treeToValueOrNull<ClassA>(jsonNodeObj)?.let { object = it } != null
        -> dosthA(object as ClassA)
    mapper.treeToValueOrNull<ClassB>(jsonNodeObj)?.let { object = it } != null
        -> dosthB(object as ClassB)
    mapper.treeToValueOrNull<ClassC>(jsonNodeObj)?.let { object = it } != null
        -> dosthC(object as ClassC)
}

pdvrieze found an even shorter solution:

val object = mapper.treeToValueOrNull<ClassA>(jsonNodeObj)
          ?: mapper.treeToValueOrNull<ClassB>(jsonNodeObj)
          ?: mapper.treeToValueOrNull<ClassC>(jsonNodeObj)

Upvotes: 2

Related Questions