我制作了一个小型序列化系统,它使用Gson
并且仅影响具有特定注释
的Fields
。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Store {
String valueName() default "";
boolean throwIfDefault() default false;
}
throwIfDefault()
确定如果 Field
的值等于默认值,是否应将其保存到文件中(我通过将字段的值与相同的字段,但在类的静态实例中)。
它工作得很好,但我想要实现的是,对于 Map
、Array
和 Set
对象也同样有效:
只有当这些对象
的条目未包含在该特定字段
的默认实例中时,才应保存它们。
它还必须适用于反序列化:
加载的对象
中尚未存在的默认值应在反序列化期间添加,或者首先加载默认的对象
,然后使用加载的条目进行修改对象
。
是否可以通过为这些对象
创建自定义Json(De)Serializer
来实现这一点,或者您将如何做到这一点?
这是反序列化部分:
public void Load() throws FileNotFoundException {
Type typeOfHashMap = new TypeToken<LinkedHashMap<String, Object>>(){}.getType();
FileReader reader = new FileReader(file);
HashMap<String, Object> loadedMap = mainGson.fromJson(reader,typeOfHashMap);
for(Field f: this.getClass().getDeclaredFields()) {
if (!f.isAnnotationPresent(Store.class)) {
continue;
}
try {
f.setAccessible(true);
Store annotation = f.getAnnotation(Store.class);
Object defaultValue = DefaultRegistrator.getDefault(this.getClass(),f);
if (!loadedMap.containsKey(annotation.valueName())) {
f.set(this, defaultValue);
continue;
}
Object loadedValue = mainGson.fromJson(
loadedMap.get(annotation.valueName()).toString(), f.getType()
);
f.set(this, loadedValue);
} catch(IllegalAccessException e) {
}
}
}
最佳答案
假设您的 JSON 对象是
{"defParam1": 999,
"defParam2": 999,
"defParam3": 999,
"param4": 999,
"param5": 999,
"param6": 999}
参数defParam1、defParam2、defParam3不会被设置。
使用默认参数将 JSON 对象解析为特定对象
默认参数在构造函数中设置,因此不需要使用注释
您的 Java 对象是:
public class ObjStore {
public ObjStore(){
this(false);
}
// Load default parameters directly into the constructor
public ObjStore(boolean loadDefault){
if( loadDefault ){
defParam1 = 123; // (int) DefaultRegistrator.getDefault("ObjStore", "defParam1");
defParam2 = 123; // (int) DefaultRegistrator.getDefault("ObjStore", "defParam2");
defParam3 = 123; // (int) DefaultRegistrator.getDefault("ObjStore", "defParam3");
}
}
public int getDefParam1() {
return defParam1;
}
public int getDefParam2() {
return defParam2;
}
public int getDefParam3() {
return defParam3;
}
public int getParam4() {
return param4;
}
public void setParam4(int param4) {
this.param4 = param4;
}
public int getParam5() {
return param5;
}
public void setParam5(int param5) {
this.param5 = param5;
}
public int getParam6() {
return param6;
}
public void setParam6(int param6) {
this.param6 = param6;
}
private int defParam1;
private int defParam2;
private int defParam3;
private int param4;
private int param5;
private int param6;
}
对于反序列化,您需要以这种方式注册新的自定义 typeAdapter:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(ObjStore.class, new JsonDeserializer<ObjStore>() {
public ObjStore deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
ObjStore objStore = new ObjStore(true);
JsonObject jo = json.getAsJsonObject();
objStore.setParam4( jo.get("param4").getAsInt() );
objStore.setParam5(jo.get("param5").getAsInt());
objStore.setParam6(jo.get("param6").getAsInt());
return objStore;
}
});
Gson gson = gsonBuilder.create();
您可以使用以下方法解析 JSON 对象:
ObjStore objStore = gson.fromJson("{\"defParam1\": 999,\"defParam2\": 999,\"defParam3\": 999,\"param4\": 999,\"param5\": 999,\"param6\": 999}", ObjStore.class);
使用默认参数将 JSON 对象解析为 Map 对象
默认参数在构造函数中设置,因此不需要使用注释。
定义包装您的 Map 对象的类
public class ObjMapStore {
public ObjMapStore(){
this(true);
}
public ObjMapStore(boolean loadDefault){
map = new HashMap<>();
if(loadDefault){
map.put("defParam1", 123); // (int) DefaultRegistrator.getDefault("ObjMapStore", "defParam1");
map.put("defParam2", 123); // (int) DefaultRegistrator.getDefault("ObjMapStore", "defParam2");
map.put("defParam3", 123); // (int) DefaultRegistrator.getDefault("ObjMapStore", "defParam3");
}
}
public void put(String key, Object value){
map.put(key, value);
}
public Map<String, Object> getMap(){
return map;
}
private Map<String, Object> map;
}
同样,为了反序列化,您需要以这种方式注册新的自定义 typeAdapter:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(ObjMapStore.class, new JsonDeserializer<ObjMapStore>() {
public ObjMapStore deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
ObjMapStore objMapStore = new ObjMapStore();
JsonObject jo = json.getAsJsonObject();
objMapStore.put("param4", jo.get("param4").getAsInt());
objMapStore.put("param5", jo.get("param5").getAsInt());
objMapStore.put("param6", jo.get("param6").getAsInt());
return objMapStore;
}
});
Gson gson = gsonBuilder.create();
就像在使用以下方法获取 map 对象之前所做的那样:
Map<String, Object> objMapStore = gson.fromJson("{\"defParam1\": 999,\"defParam2\": 999,\"defParam3\": 999,\"param4\": 999,\"param5\": 999,\"param6\": 999}", ObjMapStore.class).getMap();
对这个调用保持警惕 .getMap();
因为允许您获取定义到 ObjMapStore 返回的对象中的 Map
很高兴为您提供帮助,如有任何问题请发表评论。请记得投票并检查回复是否有帮助。再见
关于java - 如何使用 Gson 只存储非默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35106032/