web-dev-qa-db-ja.com

ジャクソンはキャストせずにJsonNodeをArrayNodeに変換する方法は?

JSONライブラリをorg.jsonからJacksonに変更しています。次のコードを移行したいと思います。

JSONObject datasets = readJSON(new URL(DATASETS));
JSONArray datasetArray =  datasets.getJSONArray("datasets");

ジャクソンには次のものがあります。

ObjectMapper m = new ObjectMapper();
JsonNode datasets = m.readTree(new URL(DATASETS));      
ArrayNode datasetArray = (ArrayNode)datasets.get("datasets");

しかし、私はそこでのキャストが好きではありません、ClassCastExceptionの可能性はありますか? org.jsongetJSONArrayに相当するメソッドがあり、配列ではない場合に適切なエラー処理を行うことができますか?

96
Konrad Höffner

はい、ジャクソンの手動パーサーの設計は他のライブラリとはまったく異なります。特に、JsonNodeには、通常他のAPIの配列ノードに関連付ける関数のほとんどが含まれていることに気付くでしょう。そのため、使用するためにArrayNodeにキャストする必要はありません。以下に例を示します。

JSON:

{
    "objects" : ["One", "Two", "Three"]
}

コード:

final String json = "{\"objects\" : [\"One\", \"Two\", \"Three\"]}";

final JsonNode arrNode = new ObjectMapper().readTree(json).get("objects");
if (arrNode.isArray()) {
    for (final JsonNode objNode : arrNode) {
        System.out.println(objNode);
    }
}

出力:

"1"
"二"
"三"

反復する前に、ノードが実際に配列であることを確認するisArrayの使用に注意してください。データ構造に完全に自信がある場合、このチェックは不要ですが、必要に応じて使用できます(これは他のほとんどのJSONライブラリと同じです)。

216
Perception

Org.jsonにgetJSONArrayと同等のメソッドがあり、配列ではない場合に適切なエラー処理を行うことができますか?

入力に依存します。つまり、URLから取得したもの。 「datasets」属性の値がプレーン配列ではなく連想配列の場合、ClassCastExceptionを取得します。

ただし、古いバージョンalsoの正確さは入力に依存します。新しいバージョンがClassCastExceptionをスローする状況では、古いバージョンはJSONExceptionをスローします。リファレンス: http://www.json.org/javadoc/org/json/JSONObject.html#getJSONArray(Java.lang.String)

1
Stephen C

一日の終わりに、ArrayNodeのデータを反復処理して消費したいと考えています。そのために:

Iterator<JsonNode> iterator = datasets.withArray("datasets").elements();
while (iterator.hasNext()) 
        System.out.print(iterator.next().toString() + " "); 

または、ストリームとラムダ関数に興味がある場合:

import com.google.common.collect.Streams;
Streams.stream(datasets.withArray("datasets").elements())
    .forEach( item -> System.out.print(item.toString()) )
0
Wildhammer