Idiomatic way of branching json parsing in kotlin


#1

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()
return 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?

PS:
msrd0 gave a good lead on this. However, I’m still stuck on finding a clean and concise way to solve this.


#2

You probably want a combination here (I’m not that familiar with ObjectMapper, but canDeserialize could avoid the try/catch. The rest is as follows:

fun <T> ObjectMapper.treeToValueOrNull(n: TreeNode, valueType: Class<T>):T? = try {
    treeToValue(n, valueType)
} catch (e: JsonProcessingException) {
    null
}

val mapper = ObjectMapper()
return mapper.treeToValueOrNull(jsonNodeObj, ClassA::class.java) ?:
       mapper.treeToValueOrNull(jsonNodeObj, ClassB::class.java) ?:
       mapper.treeToValueOrNull(jsonNodeObj, ClassC::class.java) ?:
       throw IllegalArgumentException("The node doesn't map to A, B or C")

Btw. you may make it prettier by using a refied type parameter on an inline version