3

フィールドの読み取り中に順序付けが必要な特定のクラスのデシリアライザーがあります。クラスに 2 つのフィールド (field1field2) があり、 を読み取るfield2には、最初に が必要だとしますfield1

たとえば、次の json データの場合、デシリアライザーが解析するときにfield2,field1が既に設定されているため、機能します。

{"field1": 3, "field2": 4}

ただし、フィールドを逆にすると:

{"field2": 4, "field1": 3}

field2が設定されていないjp.skipChildrenため、スキップする必要がありfield1ます。がfield1解析されると、Jackson は を再読み込みして解析する必要がありますfield2

1 つのオプションは、field2 をスキップする代わりに解析し、それを変数に保持して、field1 が設定されたときに field2 にデータを保持する変数を使用できるようにすることです。でも; の値に基づいて、field1解析する必要がない可能性があるfield2ため、コードのこの部分ではパフォーマンスが重要であるため、より良い解決策を探しています。

メソッドを使用していますが、Mapper.readValue(byte[], MyClass.class)ジャクソンがReaderBasedJsonParser解析に使用しているようです。トークンの位置を取得することはできますが、トークンの位置を設定する方法が見つかりませんでした。

4

2 に答える 2

3

最後に、私はそれを行う方法を見つけました。これは実際には回避策ですが、私が書いたテストに合格します。バイト配列を mapper.readValue に渡すとReaderBasedJsonParser、配列を反復処理して JSON ツリーを解析するものを使用します。

public static class SaveableReaderBasedJsonParser extends ReaderBasedJsonParser {
    private int savedInputPtr = -1;

    public SaveableReaderBasedJsonParser(IOContext ctxt, int features, Reader r, ObjectCodec codec, CharsToNameCanonicalizer st, char[] inputBuffer, int start, int end, boolean bufferRecyclable) {
        super(ctxt, features, r, codec, st, inputBuffer, start, end, bufferRecyclable);
    }

    public void save() {
        savedInputPtr = _inputPtr;
    }

    public boolean isSaved() {
        return savedInputPtr>-1;
    }

    public void load() {
        _currToken = JsonToken.START_OBJECT;
        _inputPtr = savedInputPtr;
        _parsingContext = _parsingContext.createChildObjectContext(0, 0);
    }
}

JsonParserthisを使用するJsonParserと、デシリアライザー EventDeserializer.deserialize(JsonParser, DeserializationContext) に渡されるインスタンスが になるSaveableReaderBasedJsonParserため、安全にキャストできます。

位置を保存したい場合は を呼び出しjp.save()て、戻る必要があるときに を呼び出すだけでよいようにしますjp.load()

私が言ったように、これは実際には回避策ですが、この種の機能が必要で、パフォーマンス上の理由からツリーを 2 回解析したくない場合は、試してみてください。

于 2015-02-15T20:52:58.957 に答える
2

カスタム デシリアライザーは、ストリーミング API を使用する必要があります。戻ったり、再解析したりする方法はありません。

この特別な処理が必要なフィールドを含むフィールド タイプまたはクラスのカスタム デシリアライザーを登録しましたか?

これらのフィールドを含むクラスのデシリアライザーを登録すると、ストリーミング API を使用して、インスタンスのすべてのフィールドを読み取り、HashMap などに一時的に格納してから、値を割り当てることができます。

ところで: あなたの質問は XYProblem のようなにおいがします。理由について別の質問を投稿する必要があるかもしれません。ここでこの問題を解決し、より良いアプローチがあるかどうかを確認する必要があります。

于 2015-02-15T07:21:15.740 に答える