LoginSignup
5
4

More than 5 years have passed since last update.

Jacksonで一部のプロパティをJSON文字列のまま取得したい!

Posted at

1. はじめに

Jacksonで簡単にJson文字列 -> Javaオブジェクトの変換処理(デシリアライズ)ができるのですが、どうしても一部のプロパティをJSON文字列のまま取得したい要件が発生しました。

何でも入る魔法のプロパティ(ここでは仮にpayloadとする)があって、別のプロパティに定義されているデータ型(FQCN)で復元したいというのが目的です。

JacksonにはJSON文字列を文字列のまま扱う@JsonValueがありますが、これはシリアライズの場合のみ有効なものです。残念ながらデシリアライズの場合は対象外です。

対処方法は独自のJsonDeserializerを実装して、@JsonDeserializeで個別にデシリアライズ処理を指定することです。といっても目的が「JSON文字列のまま取得したい」なのでJsonDeserializerの実装は非常に簡単です。

2. ソースコード

JsonRawValueDeserializer.java
package com.example.jacksondemo;

import java.io.IOException;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;

// ★ポイント1
public class JsonRawValueDeserializer extends JsonDeserializer<String> {

    // ★ポイント2
    @Override
    public String deserialize(JsonParser parser, DeserializationContext context)
            throws IOException, JsonProcessingException {
        return parser.readValueAsTree().toString();
    }
}
MyModel.java
package com.example.jacksondemo;

import java.io.Serializable;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

public class MyModel implements Serializable {

    private static final long serialVersionUID = 1L;

    // ★ポイント3
    // I want json raw text!
    @JsonDeserialize(using = JsonRawValueDeserializer.class)
    private String payload;

    // these property are auto mapped by jackson (without special operation)
    private String fqcn;
    private Integer priority;
    private String messageId;

    // constructor, setter, getter omitted
}

★ポイント1
com.fasterxml.jackson.databind.JsonDeserializerクラスを継承し、独自のJsonDeserializerを定義します。
型パラメータにはデシリアライズの処理結果の型、つまり今回はStringを指定します。

★ポイント2
deserializeメソッドをオーバーライドしてJSON文字列を返すように実装します。

★ポイント3
JSONをマッピングするJavaクラスにおいて、JSON文字列のまま値をマッピングしたいプロパティに@JsonDeserializeアノテーションを付与します。
using属性に★ポイント1で実装した独自のJsonDeserializerを指定します。

これでJSONのpayloadプロパティがオブジェクトになっていても、そのJSON文字列がそのままStringのpayloadプロパティに格納されます。
今回の目的を実現するにはdqcnプロパティを見てデータ型を特定した後、payloadプロパティのStringの値を目的のデータ型でデシリアライズしてあげればOKです。

3. さいごに

今回はJacksonのデシリアライズで一部のプロパティをJSON文字列のまま取得する方法について説明しました。
JacksonにはJsonを木構造のデータで読み込むJsonNodeという機能がありますが、JsonとJavaをマッピングする使い方が多いかと思います。その際、特定のプロパティだけはJsonのままで、という事態になった場合は今回の使い方を試してみてください。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4