Top / JSON / Json-libを使う / TIPS集

JSONの変数名とJavaフィールド名が異なる場合にマッピングを指定する

JSON/Json-libを使う/JSONからJavaへいろんな変換 のページで、Json-libを用いてJSONオブジェクトやJSON文字列からJavaオブジェクトを生成してみました。

その際に、JsonConfig?クラスを用いてJavaクラスのフィールドにあるListやSet、またMapなどのオブジェクトにどんなクラスをマッピングさせるかなどを指定できることを書きました。

さて、このJsonConfig?クラスですが、Json-libの様々な挙動を設定することができます。その前に、そもそもJson-libはデフォルトではJSON内のキー値をJavaの同じ名前のフィールド名に自動でマッピングするようにできています。具体的には

{"children":[{"name":"子の名前"},{"name":"子の名前2"}],"id":0,"name":"親の名前"} 

に対して、idやnameはJavaクラスのフィールドのidやnameという変数にマッピングします。逆にいうとキー値と変数名が異なる場合は当たり前ですが空振りしてしまうわけですね。そんなときにはJsonConfig? で設定を変更することによって、JSON内の値を任意の変数にマッピングすることができます。

試しに

{"children":[{"name":"子の名前2"}],"id":0,"name_json":"親の名前"} 

public class Parent {
  private String name;
  private int id;
  private Set children;
  
  public Set getChildren() {return children;}
  public void setChildren(Set children) {this.children = children;}
  public int getId() { return id;}
  public void setId(int id) { this.id = id;}
  public String getName() { return name;}
  public void setName(String name) { this.name = name;}
  public String toString() {
    return new ToStringBuilder(this).append("id", getId())
               .append("name",getName())
               .append("children", children).toString();
  }
}

へマッピングしてみます。JSON文字列内のname_jsonというキー値を、Javaクラスのnameフィールドにマッピングします。

まずは普通にJson-libを使用すると、

public static void main(String[] args) {
  // {"children":[{"name":"子の名前2"}],"id":0,"name_json":"親の名前"}
  // からJSONObjectを作成します
  String json = "{\"children\":[{\"name\":\"子の名前2\"}],\"id\":0,\"name_json\":\"親の名前\"} ";
  System.out.println(json);
  JSONObject jsonObject = JSONObject.fromObject(json);
  System.out.println(jsonObject);
  JsonConfig jsonConfig = createConfig();
  Parent p = (Parent) JSONObject.toBean(jsonObject, jsonConfig);
  System.out.println(p);
}

private static JsonConfig createConfig() {
  JsonConfig jsonConfig = new JsonConfig();
  jsonConfig.setRootClass(Parent.class);
  Map<String, Class> classMap = new HashMap<String, Class>();
  classMap.put("children", Child.class);
  jsonConfig.setClassMap(classMap);
  return jsonConfig;
}

実行結果は以下の通り。

{"children":[{"name":"子の名前2"}],"id":0,"name_json":"親の名前"}
Parent@ed32c4[id=0,name=<null>,children=[Child@719f1f[name=子の名前2]]]

当たり前ですがParentクラスのnameフィールドはマッピングが空振りしてnullになっています。

ではJsonConfig?に設定を追加してみます。やり方は、JSONの変数名に対してJavaフィールド名を返すメソッドを持ったクラス JavaIdentifierTransformer? を定義して設定してあげるだけですね。

実際にやってみます。createConfig() の中身を以下のように書き換えます。

private static JsonConfig createConfig() {
  JsonConfig jsonConfig = new JsonConfig();
  jsonConfig.setRootClass(Parent.class);
  Map<String, Class> classMap = new HashMap<String, Class>();
  classMap.put("children", Child.class);
  jsonConfig.setClassMap(classMap);
  jsonConfig
    .setJavaIdentifierTransformer(new JavaIdentifierTransformer() {
    @Override
    public String transformToJavaIdentifier(String param) {
      if (param != null) {
        if ("name_json".equals(param)) { //jsonのname_jsonはParentクラスのnameにマッピング
          return "name";
        }
      }
      return param;
    }
  });
  return jsonConfig;
}

このようにマッピングを指示するクラスを定義し、JsonConfig?に設定してやればOKです。実行結果は以下の通り。

{"children":[{"name":"子の名前2"}],"id":0,"name_json":"親の名前"}
Parent@caf0ed[id=0,name=親の名前,children=[Child@719f1f[name=子の名前2]]]

nameフィールドに想定通り値が設定されました。

関連リンク


この記事は

選択肢 投票
おもしろかった 3  
そうでもない 0  

Top / JSON / Json-libを使う / TIPS集

現在のアクセス:15743


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS