Skip to content

Instantly share code, notes, and snippets.

@kilink
Last active June 22, 2017 01:51
Show Gist options
  • Save kilink/e882edb1dc52035ef6000075ce774b93 to your computer and use it in GitHub Desktop.
Save kilink/e882edb1dc52035ef6000075ce774b93 to your computer and use it in GitHub Desktop.
merge data class with ObjectNode
fun main(args: Array<String>) {
val mapper = ObjectMapper().registerKotlinModule()
val obj = Foo("foo", "bar", 3)
val obj2 = merge<Foo>(obj, mapper.readValue<ObjectNode>("""{"x": "baz", "z": 5}"""))
println("obj=${obj} obj2=${obj2}, obj === obj2 is ${obj === obj2}")
}
fun <T> merge(obj: Any, json: ObjectNode): T {
require(obj::class.isData) { "Object is not an instance of a data class: $obj" }
val mapper = ObjectMapper().registerKotlinModule()
val copyMethod = obj::class.memberFunctions.find { method -> method.name == "copy" } ?:
throw RuntimeException("Couldn't find copy method on instance: $obj")
val args = mutableMapOf<KParameter, Any?>()
for (param in copyMethod.parameters) {
if (param.name == null) {
args[param] = obj
continue
}
if (!json.has(param.name)) {
if (param.isOptional) {
continue
}
throw RuntimeException("Missing required field: ${param.name}")
}
val node = json.get(param.name)
if (node.isNull && !param.type.isMarkedNullable) {
throw RuntimeException("Got null value for non-nullable field: ${param.name}")
}
val javaType = mapper.constructType(param.type.javaType)
args[param] = mapper.readerFor(javaType).readValue(node)
}
return copyMethod.callBy(args) as T
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment