やりたいこと
以下のようなJSON
から、value
プロパティだけを、型を付けてデシリアライズします。
{
"value": "10", // このプロパティは有ったりなかったりする
/* 他にも沢山のフィールド */
}
やり方
以下のような読み出し関数を作ることでできます。
サンプルコードはKotlin
ですが、Java
でも問題なく動くと思います。
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
val mapper: ObjectMapper = jacksonObjectMapper()
/**
* @param json 読み出し対象JSON
* @param targetPropertyName 読み出し対象プロパティ名
* @param dst デシリアライズ先クラス
*/
fun <T> readProperty(json: JsonNode, targetPropertyName: String, dst: Class<T>): T? {
// プロパティの読み出し(getの場合無ければnullが返ってくる)
val readedNode: JsonNode? = json.get(targetPropertyName)
// プロパティを読み出せた場合、dstに指定した型へデシリアライズする
return readedNode?.let { mapper.treeToValue(it, dst) }
}
使い方は以下のとおりです。
サンプルコードでは、value
プロパティを文字列や整数として読み出せることと、値がnull
のプロパティも問題なく読み出せることを示しています。
val rawJson = """
{
"value": "10",
"hoge": null,
"fuga": "aaa",
"piyo": 0
}
""".trimIndent()
val json: JsonNode = mapper.readTree(rawJson)
// 文字列として読み出し
val asString: String = readProperty(json, "value", String::class.java)!! // "10"
// 整数として読み出し
val asInt: Int = readProperty(json, "value", Int::class.java)!! // 10
// nullも読み出せる
val asNull: Int? = readProperty(json, "hoge", Int::class.java)
補足1: 再帰的にプロパティを見つけたい場合
ネストしたJSON
で、深い階層に有るプロパティも処理対象としたい場合、findValue
での読み出しが使えます。
- val readedNode: JsonNode? = json.get(targetPropertyName)
+ val readedNode: JsonNode? = json.findValue(targetPropertyName)
補足2: カスタムデシリアライザについて
サンプルコード内で利用しているObjectMapper
にカスタムデシリアライザを登録することで、treeToValue
の処理時にデシリアライザを適用することが可能です。