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


116

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ますか?配列ではない場合に適切なエラー処理ができるようにgetJSONArray、in と同等のメソッドはありorg.jsonますか?


残念ながら、データではフィールド名が固定されていないため、フルマッピングを使用できません。
KonradHöffner2013年

1
フィールド名が限定されたセットからのものである場合、それらすべてを備えたクラスを定義し、デシリアライザのFAIL_ON_UNKNOWN_PROPERTIES機能を使用して、未使用のフィールドにnullを返すだけにすることができます。ただし、これはもちろん、フィールド名セットが比較的限定されている場合のオプションにすぎません。
fvu 2013年

ええと、このソリューションは私の場合には最適ではないと思いますが、事前にわかっている限定セットで問題が発生する場合に備えて、それを覚えておきます。
KonradHöffner、2013年

回答:


247

はい、Jacksonの手動パーサーの設計は他のライブラリとはかなり異なります。特に、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」
「2」
「3」

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


2
あなたは私を数時間節約しました。ありがとう!
Igor Morais 2016年

"for(final JsonNode objNode:arrNode)"の行で "final"が使用されている理由を教えてください。
Anthony Vinay

5

Java 8では、次のように実行できます。

import java.util.*;
import java.util.stream.*;

List<JsonNode> datasets = StreamSupport
    .stream(datasets.get("datasets").spliterator(), false)
    .collect(Collectors.toList())

1

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

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

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


ClassCastExceptionをキャッチできるようになりました。ありがとうございます。私の好みでは、特定のJsonExceptionを持つよりも少しエレガントではありませんが、それができない場合はそれでも良いです。
KonradHöffner、2013年

0

結局のところ、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()) )
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.