簡體   English   中英

如何使用Java和Jackson庫對json字符串進行反序列化,其中對象的字段的子類包含在json字符串中

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM