1. 概要

長い間、JavaでのJSON処理の標準はありませんでした。 JSON処理に使用される最も一般的なライブラリは、JacksonとGsonです。

最近、Java EE7には、JSONを解析および生成するためのAPI( JSON 353:JSON処理用のJava API )が付属しています。

そして最後に、JEE 8のリリースには、標準化されたAPI( JSR 367:JSONバインディング用のJava API(JSON-B))があります。

今のところ、その主な実装は Eclipse Yasson(RI) ApacheJohnzonです。

2. JSON-B API

2.1. Mavenの依存関係

必要な依存関係を追加することから始めましょう。

多くの場合、選択した実装の依存関係を含めるだけで十分であり、javax.json.bind-apiは推移的に含まれることに注意してください。

<dependency>
    <groupId>javax.json.bind</groupId>
    <artifactId>javax.json.bind-api</artifactId>
    <version>1.0</version>
</dependency>

最新バージョンは、 MavenCentralにあります。

3. EclipseYassonの使用

Eclipse Yassonは、JSON Binding API( JSR-367 )の公式リファレンス実装です。

3.1. Mavenの依存関係

これを使用するには、Mavenプロジェクトに次の依存関係を含める必要があります。

<dependency>
    <groupId>org.eclipse</groupId>
    <artifactId>yasson</artifactId>
    <version>1.0.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.json</artifactId>
    <version>1.1.2</version>
</dependency>

最新バージョンは、MavenCentralにあります。

4. ApacheJohnzonを使用する

使用できるもう1つの実装は、JSON-P(JSR-353)およびJSON-B(JSR-367)APIに準拠するApacheJohnzonです。

4.1. Mavenの依存関係

これを使用するには、Mavenプロジェクトに次の依存関係を含める必要があります。

<dependency>
    <groupId>org.apache.geronimo.specs</groupId>
    <artifactId>geronimo-json_1.1_spec</artifactId>
    <version>1.0</version>
</dependency>
<dependency>
    <groupId>org.apache.johnzon</groupId>
    <artifactId>johnzon-jsonb</artifactId>
    <version>1.1.4</version>
</dependency>

最新バージョンは、MavenCentralにあります。

5. API機能

APIは、シリアル化/逆シリアル化をカスタマイズするための注釈を提供します。

簡単なクラスを作成して、構成例がどのように見えるかを見てみましょう。

public class Person {

    private int id;

    @JsonbProperty("person-name")
    private String name;
    
    @JsonbProperty(nillable = true)
    private String email;
    
    @JsonbTransient
    private int age;
     
    @JsonbDateFormat("dd-MM-yyyy")
    private LocalDate registeredDate;
    
    private BigDecimal salary;
    
    @JsonbNumberFormat(locale = "en_US", value = "#0.0")
    public BigDecimal getSalary() {
        return salary;
    }
 
    // standard getters and setters
}

シリアル化後、このクラスのオブジェクトは次のようになります。

{
   "email":"[email protected]",
   "id":1,
   "person-name":"Jhon",
   "registeredDate":"07-09-2019",
   "salary":"1000.0"
}

ここで使用される注釈は次のとおりです。

  • @JsonbProperty –カスタムフィールド名を指定するために使用されます
  • @JsonbTransient –逆シリアル化/シリアル化中にフィールドを無視する場合
  • @JsonbDateFormat –日付の表示形式を定義する場合
  • @JsonbNumberFormat –数値の表示形式を指定します
  • @JsonbNillable –null値のシリアル化を有効にするため

5.1. シリアル化と逆シリアル化

まず、オブジェクトのJSON表現を取得するには、 JsonbBuilderクラスとそのtoJson()メソッドを使用する必要があります。

まず、次のような単純なPersonオブジェクトを作成しましょう。

Person person = new Person(
  1, 
  "Jhon", 
  "[email protected]", 
  20, 
  LocalDate.of(2019, 9, 7), 
  BigDecimal.valueOf(1000));

そして、Jsonbクラスをインスタンス化します。

Jsonb jsonb = JsonbBuilder.create();

次に、toJsonメソッドを使用します。

String jsonPerson = jsonb.toJson(person);

次のJSON表現を取得するには:

{
    "email":"[email protected]",
    "id":1,
    "person-name":"Jhon",
    "registeredDate":"07-09-2019",
    "salary":"1000.0"
}

逆の方法で変換を行う場合は、fromJsonメソッドを使用できます。

Person person = jsonb.fromJson(jsonPerson, Person.class);

もちろん、コレクションを処理することもできます。

List<Person> personList = Arrays.asList(...);
String jsonArrayPerson = jsonb.toJson(personList);

次のJSON表現を取得するには:

[ 
    {
      "email":"[email protected]",
      "id":1,
      "person-name":"Jhon", 
      "registeredDate":"09-09-2019",
      "salary":"1000.0"
    },
    {
      "email":"[email protected]",
      "id":2,
      "person-name":"Jhon",
      "registeredDate":"09-09-2019",
      "salary":"1500.0"
    },
    ...
]

JSON配列からListに変換するには、 fromJsonAPIを使用します。

List<Person> personList = jsonb.fromJson(
  personJsonArray, 
  new ArrayList<Person>(){}.getClass().getGenericSuperclass()
);

5.2. JsonbConfigを使用したカスタムマッピング

JsonbConfig クラスを使用すると、すべてのクラスのマッピングプロセスをカスタマイズできます。

たとえば、デフォルトの命名戦略やプロパティの順序を変更できます。

ここで、LOWER_CASE_WITH_UNDERSCORES戦略を使用します。

JsonbConfig config = new JsonbConfig().withPropertyNamingStrategy(
  PropertyNamingStrategy.LOWER_CASE_WITH_UNDERSCORES);
Jsonb jsonb = JsonbBuilder.create(config);
String jsonPerson = jsonb.toJson(person);

次のJSON表現を取得するには:

{
   "email":"[email protected]",
   "id":1,
   "person-name":"Jhon",
   "registered_date":"07-09-2019",
   "salary":"1000.0"
}

次に、REVERSE戦略を使用してプロパティの順序を変更します。 この戦略を使用すると、プロパティの順序は辞書式順序とは逆の順序になります。 これは、コンパイル時にアノテーション@JsonbPropertyOrder。を使用して構成することもできます。実際の動作を見てみましょう。

JsonbConfig config 
  = new JsonbConfig().withPropertyOrderStrategy(PropertyOrderStrategy.REVERSE);
Jsonb jsonb = JsonbBuilder.create(config);
String jsonPerson = jsonb.toJson(person);

次のJSON表現を取得するには:

{
    "salary":"1000.0",
    "registeredDate":"07-09-2019",
    "person-name":"Jhon",
    "id":1,
    "email":"[email protected]"
}

5.3. アダプタを使用したカスタムマッピング

アノテーションとJsonbConfigクラスでは不十分な場合は、アダプターを使用できます。

それらを使用するには、次のメソッドを定義するJsonbAdapterインターフェイスを実装する必要があります。

  • AdaptToJson –このメソッドを使用すると、シリアル化プロセスにカスタム変換ロジックを使用できます。
  • AdaptFromJson –このメソッドを使用すると、逆シリアル化プロセスにカスタム変換ロジックを使用できます。

PersonAdapter を作成して、Personクラスのidおよびname属性を処理してみましょう。

public class PersonAdapter implements JsonbAdapter<Person, JsonObject> {

    @Override
    public JsonObject adaptToJson(Person p) throws Exception {
        return Json.createObjectBuilder()
          .add("id", p.getId())
          .add("name", p.getName())
          .build();
    }

    @Override
    public Person adaptFromJson(JsonObject adapted) throws Exception {
        Person person = new Person();
        person.setId(adapted.getInt("id"));
        person.setName(adapted.getString("name"));
        return person;
    }
}

さらに、アダプタをJsonbConfigインスタンスに割り当てます。

JsonbConfig config = new JsonbConfig().withAdapters(new PersonAdapter());
Jsonb jsonb = JsonbBuilder.create(config);

そして、次のJSON表現を取得します。

{
    "id":1, 
    "name":"Jhon"
}

6. 結論

このチュートリアルでは、コンパイルと実行時の両方でシリアル化と逆シリアル化をカスタマイズする例とともに、利用可能な実装を使用してJSON-BAPIをJavaアプリケーションと統合する方法の例を見ました。

完全なコードは、いつものように、Githubから入手できます。