簡體   English   中英

Java:如何編寫一個反序列化列表/集合的泛型?

[英]Java: How to write a generic that deserializes a list/collection?

我正在嘗試重構我的反序列化方法以使用泛型來反序列化任何類型。 對於不在集合中的對象,我可以很好地執行此操作,如下所示:

public static <T> T parseProductData(String jsonData, Class<T> typeClass) throws IOException, IllegalAccessException {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    T inputMessage = objectMapper.readValue(jsonData, typeClass);
    return inputMessage;
}

這是我要重構的方法:

public static List<ComponentPOCO> parseJsonComponentFromString(String fileContents){

        try {
            ObjectMapper mapper = new ObjectMapper()
                    .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
                    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            List<ComponentPOCO> component = mapper.readValue(fileContents, new TypeReference<List<ComponentPOCO>>() {});
            return component;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

這是我重構方法以使用泛型的失敗嘗試:

public static List<T> T parseJsonComponentFromString(String fileContents, Class<T> typeClass){

        try {
            ObjectMapper mapper = new ObjectMapper()
                    .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
                    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            List<T> component = mapper.readValue(fileContents, new TypeReference<List<T>>() {});
            return component;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

但是,此代碼無法編譯,因為它沒有正確使用 Java 泛型。 如何將我的 JSON 對象反序列化為通用列表/集合/類似類型?

這是我反序列化到ComponentPOCO類中的數據示例:

[
      {   "artifactPathOrUrl": "http://www.java2s.com/Code/JarDownload/sample/sample.jar.zip",
        "namespace": "exampleNamespace1",
        "name": "exampleName1",
        "tenant": "exampleTenant1"
      },

      {   
        "artifactPathOrUrl": "http://www.java2s.com/Code/JarDownload/sample-calculator/sample-calculator-bundle-2.0.jar.zip",
        "namespace": "exampleNamespace1",
        "name": "exampleName2",
        "tenant": "exampleTenant1"
      },
      {   
        "artifactPathOrUrl": "http://www.java2s.com/Code/JarDownload/helloworld/helloworld.jar.zip",
        "namespace": "exampleNamespace1",
        "name": "exampleName3",
        "tenant": "exampleTenant1"
      },
      {   
        "artifactPathOrUrl": "http://www.java2s.com/Code/JarDownload/fabric-activemq/fabric-activemq-demo-7.0.2.fuse-097.jar.zip",
        "namespace": "exampleNamespace1",
        "name": "exampleName4",
        "tenant": "exampleTenant1"
      }
]

下面是 ComponentPOCO 類型的代碼:

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.*;
import lombok.experimental.Accessors;
import org.apache.pulsar.common.io.SinkConfig;
import org.apache.pulsar.common.io.SourceConfig;

import java.util.List;
import java.util.Map;

@Setter
@Getter
@EqualsAndHashCode
@ToString
@Accessors(chain = true)
@Data
public class ComponentPOCO {
    @JsonProperty
    private String namespace;
    @JsonProperty
    private String tenant;
    @JsonProperty
    private String name;
    @JsonProperty
    private String type;
    @JsonProperty
    private String destinationTopicName;
    @JsonProperty
    private String artifactPathOrUrl;
    @JsonProperty
    private String className;
    @JsonProperty
    private List<String> inputs;
    @JsonProperty
    private String output;
    @JsonProperty
    private Map<String, Object> userConfig;
    @JsonProperty
    private String logTopic;
    @JsonProperty
    private Map<String, Object> configs;
    @JsonProperty
    private Integer parallelism;
    @JsonProperty
    public String sinkType;
    @JsonProperty
    private String sourceType;
    @JsonProperty
    public String runtimeFlags;
}

您的代碼有幾個問題。 使此代碼按我想的方式工作的最快方法是用以下方法替換該方法:

public LinkedHashMap<String,T> parseJsonComponentFromString(String fileContents){
        try {
            ObjectMapper mapper = new ObjectMapper()
                    .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
                    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            return mapper.readValue(fileContents, new TypeReference<T>() {});
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

因為ObjectMapper.readValue返回一個LinkedHashMap<String,T> (我不知道為什么它在 javadocs 中只說 T)

然后,如果您知道鍵,則使用get(key_name)查找解析后的字符串,如果不知道也不想假設它們,則forEach查找。 最后一個更好,但需要您使用 java 8+ 並了解 lambda 表達式和函數式接口。 這里有一個教程。 這是另一個。

順便說一句,我再次借機指出這段代碼有很多錯誤,您可能需要重新設計整個系統。 如果您真的真的必須使用列表,那么您會遇到不同的問題:“如何將 LinkedHashMap 轉換為列表? ”。 猜猜最快捷的方法是實現前面提到的 forEach 並將每個元素推送到 List 上。

也就是說,像這樣:

LinkedHashMap<String,Integer> linkedHashMap = XXX.parseJsonComponentFromString(yyy);
LinkedList<T> list = new LinkedList<T>();     
linkedHashMap.forEach((k,i) -> list.add(i));

希望我有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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