当前位置: 首页 > 知识库问答 >
问题:

反序列化对象时,Gson忽略null

昝宜
2023-03-14

我想在Java中反序列化包含空值的json字符串。我想将对象反序列化为properties对象。json字符串类似于:

{"prop1":null, "propr2":"fancy value"}

当我反序列化使用

String json = //
new Gson().fromJson(json, Properties.class);

由于properties对象中的hastablethat,我得到一个空指针异常。我如何指示Gson忽略空值的反序列化?

共有1个答案

薛高澹
2023-03-14

问题确实在于,GSON的默认适配器试图将null放入properties中,这是被禁止的。

要解决这个问题,您可以为properties编写自己的TypeAdapter。然后,您必须使用gsonBuilder创建Gson实例,您在该gsonBuilder上注册了该类型适配器。

下面展示了这种适配器的外观。它稍微严格一点,因为它在序列化过程中防止非字符串键和值(GSON的默认适配器不这样做),因为它们会在反序列化过程中引起问题。但是,您可以使用gson.getDelegateAdapter替换它并将序列化委托给GSON的适配器。

private static final TypeAdapter<Properties> PROPERTIES_ADAPTER = new TypeAdapter<Properties>() {
    @Override
    public Properties read(JsonReader in) throws IOException {
        in.beginObject();

        Properties properties = new Properties();
        while (in.hasNext()) {
            String name = in.nextName();
            JsonToken peeked = in.peek();

            // Ignore null values
            if (peeked == JsonToken.NULL) {
                in.nextNull();
                continue;
            }
            // Allow Json boolean
            else if (peeked == JsonToken.BOOLEAN) {
                properties.setProperty(name, Boolean.toString(in.nextBoolean()));
            }
            // Expect string or number
            else {
                properties.setProperty(name, in.nextString());
            }
        }

        in.endObject();
        return properties;
    }

    private String asString(Object obj) {
        if (obj.getClass() != String.class) {
            throw new IllegalArgumentException("Properties contains non-String object " + obj);
        }
        return (String) obj;
    }

    /*
     * Could also delegate to Gson's implementation for serialization.
     * However, that would not fail if the Properties contains non-String values,
     * which would then cause issues when deserializing the Json again. 
     */
    @Override
    public void write(JsonWriter out, Properties properties) throws IOException {
        out.beginObject();

        for (Map.Entry<Object, Object> entry : properties.entrySet()) {
            // Make sure that key is a String, otherwise properties
            // cannot be deserialized again
            out.name(asString(entry.getKey()));

            Object value = entry.getValue();
            // Be lenient and allow Numbers and Booleans as values
            if (value instanceof Number) {
                out.value((Number) value);
            } else if (value instanceof Boolean) {
                out.value((Boolean) value);
            } else {
                // Require that value is a String
                out.value(asString(value));
            }
        }

        out.endObject();
    }

}.nullSafe(); // Handle null Properties, e.g. `Properties props = null`

public static void main(String[] args) throws IOException {
    Gson gson = new GsonBuilder()
        // Register the custom type adapter
        .registerTypeAdapter(Properties.class, PROPERTIES_ADAPTER)
        .create();

    String json = "{\"prop1\":true, \"prop2\":\"text\", \"prop3\":null}";
    Properties deserialized = gson.fromJson(json, Properties.class); 
    System.out.println("Deserialized: " + deserialized);

    Properties properties = new Properties();
    properties.setProperty("prop", "text");
    // Discouraged to put non-Strings, but type adapter supports these
    properties.put("boolean", true);
    properties.put("number", 1234);
    System.out.println("Serialized: " + gson.toJson(properties));
}
 类似资料:
  • 问题内容: 我有一个简单的接口与属性的getter和setter。 我还有另一个实现此接口的UserAccount类。 我的问题是我想序列化money属性,但在反序列化它时忽略它,即,不接受用户对此属性的任何值。我在setter上尝试过@JsonIgnore,在getter上尝试过@JsonIgnore(false),它确实会忽略它,但是在序列化它时也会这样做。 我在setter上尝试了@Json

  • 我有另一个类UserAccount实现了这个接口。 我的问题是,我想序列化money属性,但在反序列化时忽略它,即不接受用户对该属性的任何值。我在setter上尝试了@jsonIgnore,在getter上尝试了@jsonIgnore(false),它确实忽略了它,但是它在序列化它的同时也忽略了它。 我在setter上尝试了@jsonIgnore,在getter上尝试了@jsonProperty,

  • 问题内容: 确定,所以我编辑了问题,因为它不够清楚。 编辑2 :更新了JSON文件。 我在Android应用程序中使用GSON,我需要解析来自服务器的JSON文件,这些文件有点太复杂了。我不想让我的对象结构太沉重,所以我想简化内容: 所以我的对象的结构将不是JSON文件的结构。 例如,如果在JSON中,我有以下内容: 我不想保留我当前的对象结构,即一个对象,其中包含一个和一个“总计”。但是我只想将

  • 主要内容:示例我们将一个Java对象序列化为一个Json文件,然后读取该Json文件以获取对象。 在这个例子中,创建一个类。 然后将对象列化后存储在文件中,该文件将具有对象的json表示形式。 示例 在中创建一个名为的Java类文件,参考以下代码 - 执行上面示例代码,得到以下结果 -

  • 我的目标是让这个电话“只是工作”。

  • 问题内容: 在这个例子中 如果JSON对象缺少属性“ age”, 有人说它不能反序列化。在反序列化期间是否有 注释 可以忽略丢失的字段? 谢谢 问题答案: 我想你想要的是 这就是Jackson 1.x的方式。我认为2.x中有一种新方法。就像是 这些将告诉Jackson仅序列化不为null的值,并且在反序列化缺少的值时不会抱怨。我认为它将只是将其设置为Java默认值。