其中一個方案是爲您創造Resource
類型的自定義解串器。在它中,使用JSON消息中的提示來決定Resource
應該是什麼類型。
我不知道你的JSON消息是什麼樣子,但解決方案會是這個樣子:
public class ResourceDeserializer implements JsonDeserializer<Resource> {
@Override
public Resource deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
final JsonObject root = json.getAsJsonObject();
final Resource resource;
if("wood".equalsIgnoreCase(root.get("type"))) {
resource = new WoodResource();
} else {
resource = new StoneResource();
}
return resource;
}
}
修訂
abstract class Resource {
protected String id;
protected Integer quantity;
}
class Wood extends Resource {}
class Stone extends Resource {}
class ResourceMap {
protected Map<String,Resource> resources;
ResourceMap() {
this.resources = new HashMap<>();
}
}
class ResourceMapDeserializer implements JsonDeserializer<ResourceMap> {
@Override
public ResourceMap deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
final JsonObject root = json.getAsJsonObject();
final ResourceMap instance = new ResourceMap();
instance.resources.put("Wood", parse(root, "Wood"));
instance.resources.put("Stone", parse(root, "Stone"));
return instance;
}
private Resource parse(JsonObject root, String fieldName) {
final JsonElement field = root.get(fieldName);
if(field != null) {
final Resource resource;
if("Wood".equalsIgnoreCase(fieldName)) {
resource = new Wood();
} else {
resource = new Stone();
}
resource.quantity = field.getAsJsonObject().get("quantity").getAsInt();
return resource;
} else {
return null;
}
}
}
簡單的驗證......
@RunWith(MockitoJUnitRunner.class)
public class ResourceDeserializerTest {
@Mock private JsonDeserializationContext mockContext;
private Gson gson;
@Before
public void setUp() {
gson = new GsonBuilder()
.registerTypeAdapter(ResourceMap.class, new ResourceMapDeserializer())
.setPrettyPrinting()
.create();
}
@Test
public void deserializes_resource_map() {
final JsonObject woodJson = new JsonObject();
woodJson.addProperty("quantity", 4);
final JsonObject stoneJson = new JsonObject();
stoneJson.addProperty("quantity", 2);
final JsonObject mapJson = new JsonObject();
mapJson.add("Wood", woodJson);
mapJson.add("Stone", stoneJson);
final ResourceMap deserialized = gson.fromJson(mapJson, ResourceMap.class);
assertThat(deserialized.resources.get("Wood").getClass()).isEqualTo(Wood.class);
assertThat(deserialized.resources.get("Stone").getClass()).isEqualTo(Stone.class);
}
}
來源
2017-06-20 01:57:13
hsl
這是一個很好的迴應,但我的問題是,我想寫一個JSON DES資源集的erializer,而不是資源。想象一下,我想反序列化這個json字符串:'{「resources」:{「Wood」:{「quantity」:4},「Stone」:{「quantity」:2}}}' –
在這種情況下,上一級「,並反序列化」Map「本身。我已經添加了更新到我的答案來演示我在說什麼。 –
hsl