簡體   English   中英

使用 GSON 時將 json NaN 序列化為 null

[英]Serialize json NaN as null when using GSON

是否可以使用 GSON 將 Double NaN 序列化為 null?

我目前遇到的問題是,當我發布 Double NaN 時,JavaScript 訂閱者無法反序列化 json 消息。

class Value {
    Double value;
}

@Test
public void name() {

    Value newValue = new Value();
    newValue.value = Double.NaN;

    Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
    String string = gson.toJson(newValue);

    System.out.println(string);

}

上面的代碼打印:

{"value":NaN}

我想:

{"value":null}

只需創建覆蓋FloatDouble類型適配器的專用類型適配器工廠,並檢查可序列化值是否為 NaN 或無窮大。

public final class NumberOnlyTypeAdapterFactory
        implements TypeAdapterFactory {

    private static final TypeAdapterFactory instance = new NumberOnlyTypeAdapterFactory();

    private static final TypeToken<Float> floatTypeToken = TypeToken.get(Float.class);
    private static final TypeToken<Double> doubleTypeToken = TypeToken.get(Double.class);

    private NumberOnlyTypeAdapterFactory() {
    }

    public static TypeAdapterFactory getInstance() {
        return instance;
    }

    @Override
    @Nullable
    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
        final Class<? super T> rawType = typeToken.getRawType();
        final TypeAdapter<? extends Number> typeAdapter;
        if ( rawType == Float.class ) {
            typeAdapter = NumberOnlyTypeAdapter.create(gson.getDelegateAdapter(this, floatTypeToken), v -> Float.isNaN(v), v -> Float.isInfinite(v));
        } else if ( rawType == Double.class ) {
            typeAdapter = NumberOnlyTypeAdapter.create(gson.getDelegateAdapter(this, doubleTypeToken), v -> Double.isNaN(v), v -> Double.isInfinite(v));
        } else {
            return null;
        }
        @SuppressWarnings("unchecked")
        final TypeAdapter<T> castTypeAdapter = (TypeAdapter<T>) typeAdapter;
        return castTypeAdapter;
    }

    @AllArgsConstructor(access = AccessLevel.PRIVATE)
    private static final class NumberOnlyTypeAdapter<T extends Number>
            extends TypeAdapter<T> {

        private final TypeAdapter<? super T> delegate;
        private final Predicate<? super T> isNan;
        private final Predicate<? super T> isInfinite;

        private static <T extends Number> TypeAdapter<T> create(final TypeAdapter<? super T> delegate, final Predicate<? super T> isNan,
                final Predicate<? super T> isInfinite) {
            return new NumberOnlyTypeAdapter<T>(delegate, isNan, isInfinite)
                    .nullSafe();
        }

        @Override
        public void write(final JsonWriter jsonWriter, final T value)
                throws IOException {
            if ( !isNan.test(value) && !isInfinite.test(value) ) {
                delegate.write(jsonWriter, value);
                return;
            }
            jsonWriter.nullValue();
        }

        @Override
        public T read(final JsonReader jsonReader) {
            throw new UnsupportedOperationException("TODO");
        }

    }

}

這是一個測試(原始 arrays 用於測試原始浮點數和雙精度數,而原始值分別裝箱為FloatDouble精度數):

public final class NumberOnlyTypeAdapterFactoryTest {

    private static final Gson gson = new GsonBuilder()
            .disableInnerClassSerialization()
            .disableHtmlEscaping()
            .registerTypeAdapterFactory(NumberOnlyTypeAdapterFactory.getInstance())
            .create();

    private static Stream<Arguments> test() {
        return Stream.of(
                Arguments.of(Float.class, 0F, Float.NaN, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, (Function<Float, float[]>) v -> new float[]{ v }),
                Arguments.of(Double.class, 0D, Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, (Function<Double, double[]>) v -> new double[]{ v })
        );
    }

    @ParameterizedTest
    @MethodSource
    public <N extends Number, A> void test(
            final Type type,
            final N zeroValue,
            final N nanValue,
            final N negativeInfinityValue,
            final N positiveInfinityValue,
            final Function<? super N, ? extends A> convertToPrimitiveArray
    ) {
        Assertions.assertEquals("0.0", gson.toJson(zeroValue));
        Assertions.assertEquals("null", gson.toJson(nanValue));
        Assertions.assertEquals("null", gson.toJson(negativeInfinityValue));
        Assertions.assertEquals("null", gson.toJson(positiveInfinityValue));
        Assertions.assertEquals("null", gson.toJson(null, type));
        Assertions.assertEquals("[0.0]", gson.toJson(convertToPrimitiveArray.apply(zeroValue)));
        Assertions.assertEquals("[null]", gson.toJson(convertToPrimitiveArray.apply(nanValue)));
        Assertions.assertEquals("[null]", gson.toJson(convertToPrimitiveArray.apply(negativeInfinityValue)));
        Assertions.assertEquals("[null]", gson.toJson(convertToPrimitiveArray.apply(positiveInfinityValue)));
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM