【问题标题】:Refactor method to use generic for deserialization重构方法以使用泛型进行反序列化
【发布时间】:2019-09-17 13:54:29
【问题描述】:

这是我要重构的方法:

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 <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;
}

下面是我反序列化到 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;
}

有没有办法让我使用这样的泛型反序列化整个列表?

【问题讨论】:

标签: java generics jackson deserialization


【解决方案1】:

您可以将与Jackson 的所有交互提取到额外的课程中并隐藏那里的所有困难。 ObjectMapper 可以创建和配置一次。对于单个对象,您可以使用 readValue(String content, Class&lt;T&gt; valueType) 方法,对于集合,您需要构建 TypeReference 并使用 readValue(String content, TypeReference valueTypeRef) 方法。简单的实现如下所示:

class JsonMapper {

  private final ObjectMapper mapper = new ObjectMapper();

  public JsonMapper() {
    // configure mapper instance if required
    mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
    mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    // etc...
  }

  public String serialise(Object value) {
    try {
      return mapper.writeValueAsString(value);
    } catch (JsonProcessingException e) {
      throw new IllegalStateException("Could not generate JSON!", e);
    }
  }

  public <T> T deserialise(String payload, Class<T> expectedClass) {
    Objects.requireNonNull(payload);
    Objects.requireNonNull(expectedClass);

    try {
      return mapper.readValue(payload, expectedClass);
    } catch (IOException e) {
      throw new IllegalStateException("JSON is not valid!", e);
    }
  }

  public <T> List<T> deserialiseList(String payload, Class<T> expectedClass) {
    Objects.requireNonNull(payload);
    Objects.requireNonNull(expectedClass);

    try {
      return mapper.readValue(payload, constructListTypeOf(expectedClass));
    } catch (IOException e) {
      throw new IllegalStateException("JSON is not valid!", e);
    }
  }

  private <T> CollectionType constructListTypeOf(Class<T> expectedClass) {
    return mapper.getTypeFactory().constructCollectionType(List.class, expectedClass);
  }
}

及用法:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

public class JsonApp {

  public static void main(String[] args) {
    JsonMapper mapper = new JsonMapper();
    System.out.println(mapper.deserialise("{\"id\":1233}", A.class));
    System.out.println(mapper.deserialiseList("[{\"id\":4567}]", A.class));
  }
}

class A {
  private int id;

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  @Override
  public String toString() {
    return "A{" + "id=" + id + '}';
  }
}

上面的代码打印:

A{id=1233}
[A{id=4567}]

另见:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多