はじめに
DAOから取得した既存のBeanのデータをそのままレスポンスにJSONとして出力したいけど、いらない項目があったり、出力形式を少し変更したり、プロパティ名を変更したりしたい、ということがあるかと思います。
そんな場合の対処法を紹介します。
やり方
まず、以下のよな既存のBeanがあったとします。
@Data
public class User {
String userId;
String userName;
String password;
Date birthday;
}
上記のうち、userNameは、nameというプロパティ名で、birthdayは"yyyy/mm/dd"形式で、そして、passwordは出力したくない、というケースがあったとします。
そういう場合の例です。
@RestController
@Transactional
public class UserListController {
@Inject
private userMapper userMapper;
// produces属性に"application/json;charset=UTF-8"を追加しないと日本語文字列が文字化けする
@PostMapping(path = "/userlist", produces = "application/json;charset=UTF-8")
public String userList() throws JsonProcessingException {
List<User> users = UserMapper.selectAll();
ObjectMapper mapper = new ObjectMapper();
// Userで定義されている項目について、JSONに出力する項目定義を追加する
mapper.addMixIn(User.class, UserView.class);
return mapper.writeValueAsString(users);
}
// JSONに出力する項目の定義
static abstract class UserView {
// 出力しないフィールド
@JsonIgnore
String password;
// 出力パターンを指定
@JsonFormat(pattern = "yyyy/MM/dd", timezone = "Asia/Tokyo")
String birthday;
// 出力するプロパティ名を指定
@JsonProperty("name")
String userName
}
}
こんな感じで、JSONに出力する項目定義用の抽象クラスを作成して、ObjectMapper#addMixIn(既存Bean.class,作成した定義クラス.class)を実行して、writeValueAsStringメソッドでJSON文字列を生成すればOKです。
注意点としては、RequestMapping(GetMapping,PostMapping)の属性にproduces = "application/json;charset=UTF-8"を付与しないと、日本語文字列が文字化けしてしまうので、別途指定が必要ということです。
なお、上記抽象クラスは、以下のようなインタフェースでも可能です。
static interface UserView {
@JsonIgnore
String getPassword();
@JsonFormat(pattern = "yyyy/MM/dd", timezone = "Asia/Tokyo")
String getBirthday();
@JsonProperty("name")
String getUserName();
}
実行すると、こんな感じのJSON文字列がレスポンスに出力されます。
{
"userId": "yamada",
"name": "山田 太郎",
"birthday": "2000/03/05"
},
{
"userId": "sato",
"name": "佐藤 花子",
"birthday": "2000/05/09"
}
余談
- JsonFormatアノテーションの
timezoneの指定をしないと、デフォルトでUTCが適用されてしまうので必須。デフォルトのタイムゾーンを適用してくれないので注意 - Spring Bootの場合は、@JsonMixinを使用すれば、ObjectMapperのインスタンスを生成する作業以降を行わなくても出来そうだが、Spring MVCでは未対応っぽい
Beanの編集OKで同じBeanを複数処理で使いまわす場合
JsonViewを利用する方法があります。
以下のサイトに説明があります。
参考サイト
以下のサイトを参考にしました。