1

Range特定の形式、つまり でシリアル化する必要がある があります"[lower,upper)"。そのために、基本的なシリアライザーを作成しました。

public class RangeSerializer extends StdSerializer<Range<?>> {

  @Override
  public void serialize(final Range<?> value, final JsonGenerator gen, final SerializerProvider provider) throws IOException {
    if (value != null) {
      gen.writeRaw('"');
      gen.writeRaw('[');
      provider.defaultSerializeValue(value.lowerEndpoint(), gen);
      gen.writeRaw(',');
      provider.defaultSerializeValue(value.upperEndpoint(), gen);
      gen.writeRaw(')');
      gen.writeRaw('"');
    }
  }

(実際にはRange、シリアライザーは、閉じた/開いた範囲、両端に無制限の範囲がある可能性などのさまざまな可能性を処理することに注意してください。単純)。

私の問題は、各クラスのデフォルトのシリアライザーにフォールバックすると、間違った場所に引用符が表示されることです。たとえばRange<String>、エントリを持つがあった場合"[foo,bar)"、それをシリアル化すると が得られ"["foo","bar")"ます。下限エンドポイント値と上限エンドポイント値を引用符なしで結果が必要です。

追加の引用符はgen.writeString()、基礎となるシリアライザーが既に文字列になっていることを認識していないためであることを理解しています。ジェネレーターにこれを知らせる方法、または私がやろうとしていることを達成する別の方法はありますか?

Range<?>本当に一般的なので、値のシリアル化をハードコーディングできないことに注意してください。Range<Integer>Range<String>、およびその他すべてで機能する必要がRange<DateTime>あります。

4

1 に答える 1

0

単一のジェネレーターを使用してすべてをシリアル化するというアプローチを取得できませんでした。を使用して特定の呼び出しをフックできるかもしれませんがDelegatingJsonGenerator、以下に示す方法の方がはるかに簡単であると判断しました (わずかなパフォーマンスの低下を犠牲にして)。

以下は、これを機能させる方法を示す Spock テスト クラスです。

@Grab('com.fasterxml.jackson.core:jackson-databind:2.8.1')
@Grab('org.spockframework:spock-core:1.0-groovy-2.4')

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import com.fasterxml.jackson.databind.util.StdConverter
import spock.lang.Specification
import spock.lang.Unroll

class RangeSerializationTest extends Specification {

    static class Range<T> {
        T lower
        T upper
    }

    @JsonSerialize(converter = RangeConverter)
    static interface RangeMixin {
    }

    static class RangeConverter extends StdConverter<Range, String> {
        private static final mapper = new ObjectMapper().disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)

        @Override
        String convert(Range value) {
            def lower = mapper.convertValue(value.lower, String)
            def upper = mapper.convertValue(value.upper, String)
            return "[$lower,$upper)"
        }
    }


    @Unroll
    def 'range of #lower.class'() {
        given:
        def mapper = new ObjectMapper()
        mapper.addMixIn(Range, RangeMixin)

        expect:
        mapper.writeValueAsString(new Range(lower: lower, upper: upper)) == expectedJson

        where:
        lower         | upper         | expectedJson
        'abc'         | 'def'         | '"[abc,def)"'
        123           | 456           | '"[123,456)"'
        new Date(123) | new Date(456) | '"[1970-01-01T00:00:00.123+0000,1970-01-01T00:00:00.456+0000)"'
    }
}
于 2016-08-26T15:07:54.580 に答える