Java GSON:编码对象的映射并在解码时保留类型
我有一门课,像:Java GSON:编码对象的映射并在解码时保留类型,java,json,gson,deserialization,json-deserialization,Java,Json,Gson,Deserialization,Json Deserialization,我有一门课,像: public class MyClass { private final Map<Property, Object> properties; } 问题是,当我试图从上面的字符串中获取MyClass实例时,NAME属性的值将是Map,而不是具有ownerName属性的类的实例。我试图编写一个自定义的序列化器/反序列化器,但仅对名称属性无法这样做。有什么想法吗?您需要为整个映射编写自定义反序列化程序。自定义反序列化程序可能如下所示: class Proper
public class MyClass {
private final Map<Property, Object> properties;
}
问题是,当我试图从上面的字符串中获取
MyClass
实例时,NAME
属性的值将是Map
,而不是具有ownerName
属性的类的实例。我试图编写一个自定义的序列化器/反序列化器
,但仅对名称
属性无法这样做。有什么想法吗?您需要为整个映射编写自定义反序列化程序。自定义反序列化程序可能如下所示:
class PropertyJsonDeserializer implements JsonDeserializer<Map<Property, Object>>, JsonSerializer<Map<Property, Object>> {
@Override
public Map<Property, Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (!json.isJsonObject()) {
return Collections.emptyMap();
}
JsonObject root = json.getAsJsonObject();
Map<Property, Object> result = new LinkedHashMap<>();
root.entrySet().forEach(entry -> {
Property property = Property.valueOf(entry.getKey());
switch (property) {
case DIVISOR:
result.put(property, entry.getValue().getAsDouble());
break;
case NAME:
Object owner = context.deserialize(entry.getValue(), Owner.class);
result.put(property, owner);
}
});
return result;
}
@Override
public JsonElement serialize(Map<Property, Object> src, Type typeOfSrc, JsonSerializationContext context) {
return context.serialize(src, Map.class);
}
}
class PropertyJsonDeserializer implements JsonDeserializer<Map<Property, Object>>, JsonSerializer<Map<Property, Object>> {
@Override
public Map<Property, Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (!json.isJsonObject()) {
return Collections.emptyMap();
}
JsonObject root = json.getAsJsonObject();
Map<Property, Object> result = new LinkedHashMap<>();
root.entrySet().forEach(entry -> {
Property property = Property.valueOf(entry.getKey());
switch (property) {
case DIVISOR:
result.put(property, entry.getValue().getAsDouble());
break;
case NAME:
Object owner = context.deserialize(entry.getValue(), Owner.class);
result.put(property, owner);
}
});
return result;
}
@Override
public JsonElement serialize(Map<Property, Object> src, Type typeOfSrc, JsonSerializationContext context) {
return context.serialize(src, Map.class);
}
}
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.annotations.JsonAdapter;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class GsonApp {
public static void main(String[] args) throws Exception {
Map<Property, Object> properties = new EnumMap<>(Property.class);
properties.put(Property.DIVISOR, new BigDecimal("33.0"));
properties.put(Property.NAME, new Owner());
MyClass myClass = new MyClass(properties);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(myClass);
System.out.println(json);
myClass = gson.fromJson(json, MyClass.class);
System.out.println(myClass);
}
}
class MyClass {
@JsonAdapter(PropertyJsonDeserializer.class)
private final Map<Property, Object> properties;
public MyClass(Map<Property, Object> properties) {
this.properties = properties;
}
// getters, setters, toString
}
class Owner {
private String ownerName = "MyBucket";
// getters, setters, toString
}
enum Property {
NAME, DIVISOR
}
{
"properties": {
"NAME": {
"ownerName": "MyBucket"
},
"DIVISOR": 33.0
}
}
MyClass{properties={NAME=Owner{ownerName='MyBucket'}, DIVISOR=33.0}}