gpt4 book ai didi

java - 判断Json中是否确实存在Gson SerializedName注释的类字段

转载 作者:行者123 更新时间:2023-11-30 03:12:35 25 4
gpt4 key购买 nike

我正在使用 google Gson 解析 json 并创建适当的对象:

public class Settings {
@SerializedName("version")
public String version = "1";

@SerializedName("ad_native_enabled")
public boolean nativeAdEnabled = false;
}

问题是我需要知道 nativeAdEnabled 的值实际上是从 json 解析的还是我指定的默认值,即 ad_native_enabled 键是否存在在 json 中,或者不是?我尝试使用 Boolean 而不是 boolean 并仅进行空检查,但 Gson 反序列化失败。这是我的 json 片段:

{
"status": "success",
"ad_native_enabled": false,
}

免责声明

在我的情况下,手动解析 json 并在该级别上进行检测是不相关和优雅的(我想在这种情况下,我必须事先欠我想要的键的列表)去检查)。非常希望以某种方式推断对象级别所需的信息。

我以 boolean 值的示例描述了一个问题,但该问题可能是广义的,并且可能涉及所有原始类型。因此,如果能有一个通用的解决方案来解决这个问题就太好了。

最佳答案

我知道你说过你已经尝试过这个,但是使用 Boolean字段应该有效。我已经将您的示例缩小了一点,并且它按预期工作。

我定义了Settings像这样的类:

public static class Settings {
@SerializedName("ad_native_enabled")
public Boolean nativeAdEnabled;
}

如果您随后解析包含该字段的 JSON:

String json = "{\"ad_native_enabled\": false}";
Settings settings = gson.fromJson(json, Settings.class);
System.out.println(settings.nativeAdEnabled); // prints false

如果您解析不包含该字段的 JSON:

String emptyJson = "{}";
Settings emptySettings = gson.fromJson(emptyJson, Settings.class);
System.out.println(emptySettings.nativeAdEnabled); // prints null

您是否将该字段的默认值保留为 false ?如果是这样,第二个示例将打印 false以及。另外,GSON 似乎并不特别喜欢 JSON 对象中最后一个属性后面的尾随逗号 - 也许这就是您收到错误的原因?

<小时/>

看到您的评论后,我更多地考虑了是否可以以某种方式支持默认值,同时仍然能够判断该字段是否存在于 JSON 中。我能想到的最佳解决方案是引入一种新的包装器类型,并带有自定义反序列化器。

我首先定义了这个包装类型,它只包含字段的实际值,以及该值是否为默认值的指示符:

public static class ValueWrapper<T> {
public final T value;
public final boolean isDefaultValue;

public ValueWrapper(T value, boolean isDefaultValue) {
this.value = value;
this.isDefaultValue = isDefaultValue;
}
}

Settings类看起来像这样:

public static class Settings {
@SerializedName("ad_native_enabled")
public ValueWrapper<Boolean> nativeAdEnabled = new ValueWrapper<>(false, true);
}

这里我将该字段定义为具有值 false默认情况下,这就是 isDefaultValue 的原因设置为true .

然后我为此类型定义了一个自定义反序列化器。基本思想是采用 ValueWrapper 的类型您正在尝试反序列化,提取其泛型参数,将 JSON 中的实际值反序列化为泛型参数类型,然后返回一个新的 ValueWrapper哪里isDefaultValue设置为false 。这个解串器看起来像这样:

public static class ValueWrapperDeserializer implements JsonDeserializer<ValueWrapper<?>> {
@Override
public ValueWrapper<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
ParameterizedType parameterizedType = (ParameterizedType) typeOfT;
Type valueType = parameterizedType.getActualTypeArguments()[0];
Object value = context.deserialize(json, valueType);
return new ValueWrapper<>(value, false);
}
}

现在我们需要做的就是注册自定义反序列化器:

    Gson gson = new GsonBuilder()
.registerTypeAdapter(ValueWrapper.class, new ValueWrapperDeserializer())
.create();

然后我们可以运行上面的两个示例:

String json = "{\"ad_native_enabled\": false}";
Settings settings = gson.fromJson(json, Settings.class);
System.out.println(settings.nativeAdEnabled.value); // prints false
System.out.println(settings.nativeAdEnabled.isDefaultValue); // prints false

String emptyJson = "{}";
Settings emptySettings = gson.fromJson(emptyJson, Settings.class);
System.out.println(emptySettings.nativeAdEnabled.value); // prints false
System.out.println(emptySettings.nativeAdEnabled.isDefaultValue); //prints true

因此,这允许我们拥有默认值,但仍然能够使用 isDefaultValue 判断该字段是否已设置。 。这显然对Settings的用户的API产生了相当大的影响。对象,但这也许比处理空值并将默认值存储在其他地方更简洁。

关于java - 判断Json中是否确实存在Gson SerializedName注释的类字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33310439/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com