![](/img/trans.png)
[英]How can I deserialize a Json String to get polymorphic result using Java and Jackson Library?
[英]How can i deserialize Json string where object's field's subclass is included in json string, using Java and Jackson library
我是Java的新手。 我有一些類Site,Instances,CloudInstance。 類Site具有屬性實例,類CloudInstance繼承類Instance。 他們如下─
public class Site extends BaseEntity {
private String siteName;
List<Instance> instances = Lists.newArrayList();
}
public class Instance extends BaseEntity {
private String instanceId;
private String name;
}
public class CloudInstance extends Instance {
private String availabilityZone;
private String instanceType
}
我正在反序列化json字符串如下 -
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper mapper = new ObjectMapper();
BaseEntity obj = null;
obj = (BaseEntity) mapper.readValue(jsonStr, Site.class);
如果我的jsonStr不包含類“CloudInstance”的字段並且包含具有Instance類的字段的字段實例,則它可以正常工作。
問題 - 現在我想反序列化jsonStr,其中包括'CloudInstance'classe的fiels以及'Site'類的'instances'字段。 Ex jsonStr如下 -
{
"id": null,
"siteName": "demo",
"instances": [
{
"instanceId": "i-8c2ee5fc",
"name": "some-node",
"availabilityZone": "some-zone",
"instanceType": "t1.micro"
}]
}
對於上面的jsonStr我得到以下錯誤
error: Unrecognized field \"availabilityZone\" and error: Unrecognized field \"instanceType\"
有很多if else和臟代碼我可以獲得Site的obj,包括上面的字段。 但我想為此實施清潔解決方案。 有沒有可以做到這一點的圖書館? 任何有價值的幫助。 請幫忙..!!
提前致謝。
您要實現的目標稱為多態反序列化。 您的示例失敗,因為Jackson需要知道應該從JSON構造什么實例類型並將其放置到實例列表中。 有關詳細說明,請參閱此 Wiki頁面。
我已經修改了你的例子來演示它是如何工作的。 我在JSON表示中的@type
字段中添加了實例類型信息。 我還使用@JsonCreator注釋注釋的構造函數創建實例,使所有類都不可變 。
public class JacksonPolymorphism {
public static class BaseEntity {
private final String id;
protected BaseEntity(String id) {
this.id = id;
}
}
public static class Site extends BaseEntity {
private final String siteName;
private final List<Instance> instances;
@JsonCreator
public Site(@JsonProperty("id") String id,
@JsonProperty("siteName") String siteName,
@JsonProperty("instances") List<Instance> instances) {
super(id);
this.siteName = siteName;
this.instances = instances;
}
@Override
public String toString() {
return "Site{" +
"siteName='" + siteName + '\'' +
", instances=" + instances +
'}';
}
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "@type")
@JsonTypeName(value = "simple")
public static class Instance extends BaseEntity {
private final String name;
@JsonCreator
public Instance(@JsonProperty("instanceId") String id,
@JsonProperty("name") String name) {
super(id);
this.name = name;
}
@Override
public String toString() {
return "Instance{" +
"name='" + name + '\'' +
'}';
}
}
@JsonTypeName("cloud")
public static class CloudInstance extends Instance {
private final String availabilityZone;
private final String instanceType;
public CloudInstance(@JsonProperty("instanceId") String id,
@JsonProperty("name") String name,
@JsonProperty("availabilityZone") String availabilityZone,
@JsonProperty("instanceType") String instanceType) {
super(id, name);
this.availabilityZone = availabilityZone;
this.instanceType = instanceType;
}
@Override
public String toString() {
return "CloudInstance{" +
"availabilityZone='" + availabilityZone + '\'' +
", instanceType='" + instanceType + '\'' +
'}';
}
}
public static final String JSON = "{\n" +
" \"id\": null,\n" +
" \"siteName\": \"demo\",\n" +
" \"instances\": [\n" +
" {\n" +
" \"@type\": \"cloud\",\n" +
" \"instanceId\": \"i-8c2ee5fc\",\n" +
" \"name\": \"some-node\",\n" +
" \"availabilityZone\": \"some-zone\",\n" +
" \"instanceType\": \"t1.micro\" \n" +
" }," +
" {\n" +
" \"@type\": \"simple\",\n" +
" \"instanceId\": \"ABC\",\n" +
" \"name\": \"FGF\"\n" +
" }]" +
" }";
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.registerSubtypes(CloudInstance.class);
System.out.println(mapper.readValue(JSON, Site.class));
}
}
輸出:
Site{siteName='demo', instances=[CloudInstance{availabilityZone='some-zone', instanceType='t1.micro'}, Instance{name='FGF'}]}
我一直有問題反序列化包含List <...>對象與傑克遜的JSON,所以嘗試用Gson反序列化:
https://code.google.com/p/google-gson/
看看json和toJson方法中的文檔。
我希望能有所幫助,祝你好運
從未與Jackson或Gson保持一致的運氣,請嘗試使用Flex JSON :
JSONSerializer ser = new JSONSerializer();
String json = ser.deepSerialize(yourObject);
JSONDeserializer<YourMainType> der = new JSONDeserializer<YourMainType>();
YourMainType mainType = der.deserialize(json);
為此,所有需要序列化/反序列化的類必須公開與Java Beans約定一致的getter / setter。
您可以使用GSON Library將Json反序列化為類對象。
有一個函數gson.fromJson(JSON String)
將json字符串轉換為類對象。
這是示例代碼:
Gson json = new Gson();
Site site = json.fromJson(jsonStr, Site.class);
但是在你的代碼中你已經取代了
List<Instance> instances = Lists.newArrayList();
這個系列在Site
類中
List<CloudInstance> instances = new ArrayList<CloudInstance>();
因為您的CloudInstance
類擴展了Instance
所以它意味着CloudInstance
類包含Instance
類的成員。 根據json,你需要這樣做直接轉換為類對象。
願這對你有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.