首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用GSON时将json NaN序列化为空。

使用GSON时将json NaN序列化为空。
EN

Stack Overflow用户
提问于 2021-05-26 14:23:49
回答 1查看 901关注 0票数 0

是否可以用GSON将双NaN序列化为null?

我目前面临的问题是,当我发布双NaN时,JavaScript订阅服务器无法反序列化json。

代码语言:javascript
复制
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);

}

以上代码打印:

代码语言:javascript
复制
{"value":NaN}

我想:

代码语言:javascript
复制
{"value":null}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-27 07:52:09

只需创建覆盖FloatDouble类型适配器的专用类型适配器工厂,并检查可序列化的值是否为NaNs,甚至可能是无穷大值。

代码语言:javascript
复制
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");
        }

    }

}

下面是一个测试(原语数组用于测试原始浮点数和双值,而原始值分别以FloatDouble形式装箱):

代码语言:javascript
复制
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)));
    }

}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67706911

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档