1概要

このチュートリアルはJackson



treeモデルノードを扱うことに焦点を合わせます。

ノードの追加、変更、削除だけでなく、さまざまな変換に

JsonNode

を使用します。


2ノードを作成する

ノード作成の最初のステップは、デフォルトのコンストラクタを使用して

ObjectMapper

オブジェクトをインスタンス化することです。

ObjectMapper mapper = new ObjectMapper();


ObjectMapper

オブジェクトの作成はコストがかかるため、同じオブジェクトを複数の操作に再利用することをお勧めします。

次に、

ObjectMapper

を取得したら、ツリーノードを作成する3つの方法があります。


2.1. 最初からノードを構築

何もしないでノードを作成する最も一般的な方法は次のとおりです。

JsonNode node = mapper.createObjectNode();

あるいは、

JsonNodeFactory

を介してノードを作成することもできます。

JsonNode node = JsonNodeFactory.instance.objectNode();


2.2. JSONソースから解析する

この方法はリンクでよくカバーされています:/jackson-json-to-jsonnode[ジャクソン – マーシャルストリングからJsonNode]記事。もっと情報が必要な場合はそれを参照してください。


2.3. オブジェクトから変換する


ObjectMapper



valueToTree(Object fromValue)

メソッドを呼び出すことで、ノードをJavaオブジェクトから変換できます。

JsonNode node = mapper.valueToTree(fromValue);


convertValue

APIも役立ちます。

JsonNode node = mapper.convertValue(fromValue, JsonNode.class);

実際にどのように機能するか見てみましょう。

NodeBean

という名前のクラスがあるとします。

public class NodeBean {
    private int id;
    private String name;

    public NodeBean() {
    }

    public NodeBean(int id, String name) {
        this.id = id;
        this.name = name;
    }

   //standard getters and setters
}

変換が正しく行われることを確認するテストを書きましょう。

@Test
public void givenAnObject__whenConvertingIntoNode__thenCorrect() {
    NodeBean fromValue = new NodeBean(2016, "baeldung.com");

    JsonNode node = mapper.valueToTree(fromValue);

    assertEquals(2016, node.get("id").intValue());
    assertEquals("baeldung.com", node.get("name").textValue());
}


3ノードを変換する


3.1. JSONとして書き出す

ツリーノードをJSON文字列に変換する基本的な方法は次のとおりです。

mapper.writeValue(destination, node);

宛先は

File



OutputStream

、または

Writer

です。 +セクション2.3で宣言されたクラス

NodeBean

を再利用することで、テストはこのメソッドが期待通りに動作することを確認します。

final String pathToTestFile = "node__to__json__test.json";

@Test
public void givenANode__whenModifyingIt__thenCorrect() throws IOException {
    String newString = "{\"nick\": \"cowtowncoder\"}";
    JsonNode newNode = mapper.readTree(newString);

    JsonNode rootNode = ExampleStructure.getExampleRoot();
    ((ObjectNode) rootNode).set("name", newNode);

    assertFalse(rootNode.path("name").path("nick").isMissingNode());
    assertEquals("cowtowncoder", rootNode.path("name").path("nick").textValue());
}


3.2. オブジェクトに変換する


JsonNode

をJavaオブジェクトに変換する最も便利な方法は

treeToValue

APIです。

NodeBean toValue = mapper.treeToValue(node, NodeBean.class);

機能的には次のものと同等です。

NodeBean toValue = mapper.convertValue(node, NodeBean.class)

トークンストリームを介してそれを行うこともできます。

JsonParser parser = mapper.treeAsTokens(node);
NodeBean toValue = mapper.readValue(parser, NodeBean.class);

最後に、変換プロセスを検証するテストを実装しましょう。

@Test
public void givenANode__whenConvertingIntoAnObject__thenCorrect()
  throws JsonProcessingException {
    JsonNode node = mapper.createObjectNode();
    ((ObjectNode) node).put("id", 2016);
    ((ObjectNode) node).put("name", "baeldung.com");

    NodeBean toValue = mapper.treeToValue(node, NodeBean.class);

    assertEquals(2016, toValue.getId());
    assertEquals("baeldung.com", toValue.getName());
}


4ツリーノードの操作


example.json

という名前のファイルに含まれる次のJSON要素は、このセクションで説明するアクションの基本構造として使用されます。

{
    "name":
        {
            "first": "Tatu",
            "last": "Saloranta"
        },

    "title": "Jackson founder",
    "company": "FasterXML"
}

クラスパスにあるこのJSONファイルは、モデルツリーに解析されます。

public class ExampleStructure {
    private static ObjectMapper mapper = new ObjectMapper();

    static JsonNode getExampleRoot() throws IOException {
        InputStream exampleInput =
          ExampleStructure.class.getClassLoader()
          .getResourceAsStream("example.json");

        JsonNode rootNode = mapper.readTree(exampleInput);
        return rootNode;
    }
}

次のサブセクションでノードの操作を説明するときにツリーのルートが使用されることに注意してください。


4.1. ノードを探す

ノードを操作する前に、まず最初に必要なことは、それを見つけて変数に割り当てることです。

ノードへのパスが事前にわかっている場合は、それは非常に簡単です。

たとえば、

last

という名前のノードが必要で、これが

name

ノードの下にあるとします。

JsonNode locatedNode = rootNode.path("name").path("last");

あるいは、

path

の代わりに

get

または

with

APIを使用することもできます。

パスがわからない場合は、もちろん検索はより複雑で反復的になります。


4.2. 新しいノードを追加する

次のように、ノードを別のノードの子として追加できます。

ObjectNode newNode = ((ObjectNode) locatedNode).put(fieldName, value);


put

の多くのオーバーロードされた変形は、異なる値型の新しいノードを追加するために使われるかもしれません。


putArray



putObject



PutPOJO



putRawValue

、および

putNull

など、他の多くの類似したメソッドも使用できます。

最後に、例を見てみましょう。ツリーのルートノードに構造全体を追加します。

"address":
{
    "city": "Seattle",
    "state": "Washington",
    "country": "United States"
}

これが、これらすべての操作を実行して結果を検証するための完全なテストです。

@Test
public void givenANode__whenAddingIntoATree__thenCorrect() throws IOException {
    JsonNode rootNode = ExampleStructure.getExampleRoot();
    ObjectNode addedNode = ((ObjectNode) rootNode).putObject("address");
    addedNode
      .put("city", "Seattle")
      .put("state", "Washington")
      .put("country", "United States");

    assertFalse(rootNode.path("address").isMissingNode());

    assertEquals("Seattle", rootNode.path("address").path("city").textValue());
    assertEquals("Washington", rootNode.path("address").path("state").textValue());
    assertEquals(
      "United States", rootNode.path("address").path("country").textValue();
}


4.3. ノードを編集する


ObjectNode

インスタンスは、

set(String fieldName、JsonNode value)

メソッドを呼び出すことによって変更できます。

JsonNode locatedNode = locatedNode.set(fieldName, value);

同じタイプのオブジェクトに対して

replace

または

setAll

メソッドを使用しても、同様の結果が得られる可能性があります。

メソッドが期待どおりに機能することを確認するために、ルートノードの下のフィールド

name

の値を

first

および

last

のオブジェクトから

nick

フィールドのみで構成される別のものにテストで変更します。

@Test
public void givenANode__whenModifyingIt__thenCorrect() throws IOException {
    String newString = "{\"nick\": \"cowtowncoder\"}";
    JsonNode newNode = mapper.readTree(newString);

    JsonNode rootNode = ExampleStructure.getExampleRoot();
    ((ObjectNode) rootNode).set("name", newNode);

    assertFalse(rootNode.path("name").path("nick").isMissingNode());
    assertEquals("cowtowncoder", rootNode.path("name").path("nick").textValue());
}


4.4. ノードを削除する

親ノードで

remove(String fieldName)

APIを呼び出すことで、ノードを削除できます。

JsonNode removedNode = locatedNode.remove(fieldName);

一度に複数のノードを削除するために、

Collection <String>

typeのパラメータを使用してオーバーロードされたメソッドを呼び出すことができます。これは、削除されるノードの代わりに親ノードを返します。

ObjectNode locatedNode = locatedNode.remove(fieldNames);

極端な場合、特定のノードのすべてのサブノードを削除したい場合は、

removeAll

APIが役立ちます。

次のテストでは、上記の最初の方法に焦点を当てます。これが最も一般的なシナリオです。

@Test
public void givenANode__whenRemovingFromATree__thenCorrect() throws IOException {
    JsonNode rootNode = ExampleStructure.getExampleRoot();
    ((ObjectNode) rootNode).remove("company");

    assertTrue(rootNode.path("company").isMissingNode());
}


5結論

このチュートリアルでは、Jacksonでツリーモデルを扱うための一般的なAPIとシナリオについて説明しました。

そして、いつものように、これらすべての例とコードスニペットの実装は


over GitHub


にあります。プロジェクトなので、そのままインポートして実行するのは簡単なはずです。