【问题标题】:gson: Treat null as empty Stringgson:将 null 视为空字符串
【发布时间】:2012-02-28 14:04:15
【问题描述】:

我使用google-gson 将Java 映射序列化为JSON 字符串。它提供a builder handles null values:

Gson gson = new GsonBuilder().serializeNulls().create();

问题是结果是字符串null,如:

gson.toJson(categoriesMap));
{"111111111":null}

而要求的结果是:

{"111111111":""}

我可以对null"" 进行字符串替换,但这很难看并且容易出错。是否有原生 gson 支持添加自定义字符串而不是 null

【问题讨论】:

  • 旁注:null 是一个有效的 json 值。见json.org

标签: json parsing gson


【解决方案1】:

上面的答案对于序列化是可以的,但是在反序列化的时候,如果有一个空值的字段,Gson会跳过它并且不会进入类型适配器的反序列化方法,因此你需要注册一个TypeAdapterFactory并返回在里面输入适配器。

Gson gson = GsonBuilder().registerTypeAdapterFactory(new NullStringToEmptyAdapterFactory()).create();


public static class NullStringToEmptyAdapterFactory<T> implements TypeAdapterFactory {
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {

        Class<T> rawType = (Class<T>) type.getRawType();
        if (rawType != String.class) {
            return null;
        }
        return (TypeAdapter<T>) new StringAdapter();
    }
}

public static class StringAdapter extends TypeAdapter<String> {
    public String read(JsonReader reader) throws IOException {
        if (reader.peek() == JsonToken.NULL) {
            reader.nextNull();
            return "";
        }
        return reader.nextString();
    }
    public void write(JsonWriter writer, String value) throws IOException {
        if (value == null) {
            writer.nullValue();
            return;
        }
        writer.value(value);
    }
}

【讨论】:

  • 嗨@oznus。据我了解,Gson 不会解析键的 Json.Null 值。它将初始化 POJO 类中的默认值。因此,您可以在默认构造函数中初始化变量,而不是添加 TypeAdapter。如果我错了,请纠正我。请阅读此sites.google.com/site/gson/gson-user-guide#NullObjectSupport
  • 我只用了适配器部分。此处不需要 AdapterFactory。
  • 它适用于我在 json 对象中来自服务器的结果为 null 并且上面的公式转换为空白字符串 (" ")。
  • 请注意,用于 GsonBuilder 的方法是 registerTypeAdapterFactory,而不是您可能已经在使用的 registerTypeAdapter。
  • Gson 的实现者似乎并不关心简化他们的 API。 Alessio's 答案很简单。
【解决方案2】:

在 gson 的实际版本中,您可以这样做:

    Object instance = c.getConstructor().newInstance();
    GsonBuilder gb = new GsonBuilder(); 
    gb.serializeNulls();
    Gson gson = gb.create(); 
    String stringJson = gson.toJson(instance);

【讨论】:

  • @avalon 这会返回该对象的所有字段,我只想要那个为空且存在于 json 中的字段,因此任何解决方案
【解决方案3】:

Google groups的回答

我也有同样的情况。这个示例帮助了我。

import java.lang.reflect.Type;

public class StringConverter implements JsonSerializer<String>, 
    JsonDeserializer<String> { 
public JsonElement serialize(String src, Type typeOfSrc, 
    JsonSerializationContext context) { 
    if ( src == null ) { 
        return new JsonPrimitive(""); 
    } else { 
        return new JsonPrimitive(src.toString());
    }
} 
public String deserialize(JsonElement json, Type typeOfT, 
    JsonDeserializationContext context) 
        throws JsonParseException { 
    return json.getAsJsonPrimitive().getAsString(); 
} 
}

并使用:

GsonBuilder gb = new GsonBuilder(); 
gb.registerTypeAdapter(String.class, new StringConverter()); 
Gson gson = gb.create(); 

【讨论】:

    【解决方案4】:

    如果这是您的应用程序类型,您可以注册一个类型适配器。但是 Gson 不允许您更改字符串或原始类型的序列化形式。

    最好的办法是更改 Java 对象。或者放松对空值的限制。

    【讨论】:

    【解决方案5】:

    没有解决办法。我有opened an issue at Gson's page;希望下个版本能修复。

    【讨论】:

      【解决方案6】:

      我遇到了几乎相同的问题,我可以解决。 我也创建了一个issue

      我从lyubomyr-shaydariv得到这个答案:

      我猜,Gson 不会因为性能原因和简单性而触及缺失值。您可以轻松实现一个后处理类型适配器,它将应该是可选的不受影响的空字段设置为其默认值

      基于original answer的代码sn-p我写了一个sample projectunit tests

      【讨论】:

        猜你喜欢
        • 2020-07-06
        • 1970-01-01
        • 1970-01-01
        • 2018-07-25
        • 1970-01-01
        • 1970-01-01
        • 2010-09-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多