LoginSignup
6
8

More than 5 years have passed since last update.

JSONデータ/JSON SchemaからJavaマッパークラスを生成する方法および、オプションについて

Last updated at Posted at 2016-03-18

目的

XMLよりJSONのほうがデータ量が少なくなるため、JSONデータからJavaマッパークラスを生成する方法について調べてみた。

結果

「jsonschema2pojo-core」ライブラリを使って「Jackson」形式のJavaマッパークラスを自動生成出来た。
Javaマッパークラスのアノテーション形式については「Jackson 2.x、Jackson 1.x、Gson、None」から選べる。
Web/maven/gradle/cliからも利用できる。

自動生成結果での注意事項

クラス名がかぶると「name_.java」のように別名でクラスが生成されます。
JSONデータから生成する際、array要素が0または、1つの場合に期待した出力と食い違う場合があります。

補足

そもそもなんで、クラスなんて作るのってところはeclipseで補完機能使いたかったから。
ちょこっと扱いたいなら、以下のように書けばオブジェクトを取得できる。
「org.json:json:20080701.jar」使用。

org.json.JSONObject jsonObject = new org.json.JSONObject(jsonString);

環境

  • Windows 10 Pro 1511 (x64)
  • JDK8 u73
  • Eclipse IDE for Java Developers Mars 2
  • jsonschema2pojo-core
    • 0.4.21

ビルド設定

build.gradle

apply plugin: 'java'

repositories { mavenCentral() }


// set encoding
def defaultEncoding = 'UTF-8'
tasks.withType(AbstractCompile).each { it.options.encoding = defaultEncoding }
tasks.withType(GroovyCompile).each { it.groovyOptions.encoding = defaultEncoding }

dependencies {

  // JOSN -> Java用
  compile 'org.jsonschema2pojo:jsonschema2pojo-core:0.4.21';
  testCompile 'junit:junit:4.12'

}

サンプルソース

設定については「DefaultGenerationConfig」を継承してメソッドをオーバーライドする形となる。
JSONToJava.java

package sample.rest.json.client.generator;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.logging.Logger;

import org.jsonschema2pojo.DefaultGenerationConfig;
import org.jsonschema2pojo.GenerationConfig;
import org.jsonschema2pojo.Jackson2Annotator;
import org.jsonschema2pojo.SchemaGenerator;
import org.jsonschema2pojo.SchemaMapper;
import org.jsonschema2pojo.SchemaStore;
import org.jsonschema2pojo.SourceType;
import org.jsonschema2pojo.rules.RuleFactory;

import com.sun.codemodel.JCodeModel;

public class JSONToJava {

  private static final Logger log = Logger.getLogger(JSONToJava.class.getName());

  public static void main(String[] args) {

    Path outputPath = null;
    try {
      StringBuilder jsonStringBuilder = new StringBuilder();
      jsonStringBuilder.append("{");
      jsonStringBuilder.append(" \"name\": \"foor\",");
      jsonStringBuilder.append(" \"age\": 18");
      jsonStringBuilder.append("}");
      outputPath = Files.createTempDirectory(null);
      String packageName = "sandbox.foo";
      String rootClassName = "Root";
      JSONToJava jsonToJava =
          new JSONToJava(jsonStringBuilder.toString(), outputPath, packageName, rootClassName);
      jsonToJava.execute();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      log.info("「" + outputPath + "」に出力しました。");
    }
  }


  private String jsonString;
  private Path outputPath;
  private String packageName;
  private String rootClassName;

  public JSONToJava(String jsonString, Path outputPath, String packageName, String rootClassName) {
    this.jsonString = jsonString;
    this.outputPath = outputPath;
    this.packageName = packageName;
    this.rootClassName = rootClassName;
  }

  public void execute() throws IOException {

    JCodeModel codeModel = new JCodeModel();
    GenerationConfig generationConfig = new DefaultGenerationConfig() {
      @Override
      public SourceType getSourceType() {
        return SourceType.JSON;
      }

      @Override
      public boolean isIncludeHashcodeAndEquals() {
        return false;
      }

      @Override
      public boolean isIncludeToString() {
        return false;
      }

      @Override
      public boolean isIncludeAdditionalProperties() {
        return false;
      }

      @Override
      public boolean isIncludeDynamicAccessors() {
        return false;
      }
    };

    SchemaMapper mapper = new SchemaMapper(
        new RuleFactory(generationConfig, new Jackson2Annotator(), new SchemaStore()),
        new SchemaGenerator());
    mapper.generate(codeModel, rootClassName, packageName, jsonString);

    codeModel.build(outputPath.toFile());
  }

}

入力データ(JSONデータ)

{
 "name": "foor",
 "age": 18
}

出力結果(Javaマッパークラス)

Root.java


package sandbox.foo;

import javax.annotation.Generated;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@JsonInclude(JsonInclude.Include.NON_NULL)
@Generated("org.jsonschema2pojo")
@JsonPropertyOrder({
    "name",
    "age"
})
public class Root {

    @JsonProperty("name")
    private String name;
    @JsonProperty("age")
    private Integer age;

    /**
     * 
     * @return
     *     The name
     */
    @JsonProperty("name")
    public String getName() {
        return name;
    }

    /**
     * 
     * @param name
     *     The name
     */
    @JsonProperty("name")
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 
     * @return
     *     The age
     */
    @JsonProperty("age")
    public Integer getAge() {
        return age;
    }

    /**
     * 
     * @param age
     *     The age
     */
    @JsonProperty("age")
    public void setAge(Integer age) {
        this.age = age;
    }

}

生成オプション

org.jsonschema2pojo.DefaultGenerationConfig

メソッド名 戻り値(型) デフォルト値
getSource() Iterator Exception 入力ファイル/ディレクトリ指定
getSourceType() SourceType SourceType.JSONSCHEMA 入力種別指定(jsonschema、json)
getTargetDirectory() File new File(".") 出力先ディレクトリ指定
isRemoveOldOutput() boolean false 出力ディレクトリ削除
getTargetPackage() String "" 出力パッケージ名の指定
getOutputEncoding() String UTF-8 出力文字コード
getTargetVersion() String 1.6 対象バージョン指定
isGenerateBuilders() boolean false builder作成
isUsePrimitives() boolean false プリミティブ変数の使用
getPropertyWordDelimiters() char[] new char[] { '-', ' ', '_' } フィールド名生成時に除去される文字列
isUseLongIntegers() boolean false json(integer)の場合longの使用
isUseDoubleNumbers() boolean true json(number)の場合doubleの使用
isIncludeHashcodeAndEquals() boolean true toHash()、toEquals()の生成(commons.lang)
isIncludeToString() boolean true toString()の生成(commons.lang)
getAnnotationStyle() AnnotationStyle AnnotationStyle.JACKSON アノテーションスタイル(Jackson 2.x、Jackson 1.x、Gson、None)
getCustomAnnotator() Class<? extends Annotator> NoopAnnotator.class カスタムアノテーション
getCustomRuleFactory() Class<? extends RuleFactory> RuleFactory.class カスタムルールファクトリー
isIncludeJsr303Annotations() boolean false JSR303アノテーション(Bean Validation)出力
isUseJodaDates() boolean false org.joda.time.DateTime使用
isUseJodaLocalDates() boolean false org.joda.time.LocalDate使用
isUseJodaLocalTimes() boolean false org.joda.time.LocalTime使用
isUseCommonsLang3() boolean false commons-langをcommons-lang3に置き換え
isParcelable() boolean false Parcelable実装(Android)
getFileFilter() FileFilter new AllFileFilter() 入力ディレクトリ指定の場合使用可能
isInitializeCollections() boolean true コレクションの初期化
getClassNamePrefix() String "" 接頭語
getClassNameSuffix() String "" 接尾語
isIncludeConstructors() boolean false コンストラクタ生成
isConstructorsRequiredPropertiesOnly() boolean false コンストラクタ生成時必須項目のみ
isIncludeAdditionalProperties() boolean true 追加プロパティの許可
isIncludeAccessors() boolean true get/set生成
isIncludeDynamicAccessors() boolean true declaredPropertyが生成される
getDateTimeType() String null 日付型指定(例:java.time.LocalDateTime)(優先)
getDateType() String null 日付型指定(例:java.time.LocalDate)(優先)
getTimeType() String null 日付型指定(例:java.time.LocalTime)(優先)

参考資料

jsonschema2pojo
jsonschema2pojo Web版

6
8
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
6
8