如何使杰克逊将泛型类注入到bean中?

时间:2019-06-11 14:09:54

标签: java json jackson

让我们假设,我们有一个像这样的bean:

public class Response<T> {

    private T data;
    private double executionDuration;
    private boolean success;
    private String version;

    //HOW TO Make Jackson to inject this?
    private Class<T> dataClass;

    public Optional<T> getData() {
        return Optional.ofNullable(data);
    }

    public double getExecutionDuration() {
        return executionDuration;
    }

    public Class<T> getDataClass() {
        return dataClass;
    }

    public String getVersion() {
        return version;
    }

    public boolean isSuccess() {
        return success;
    }
}

反序列化的过程如下:

objectMapper.readValue(json, new TypeReference<Response<SomeClass>>() {});

我可以以某种方式让Jackson将类“ SomeClass”注入到我的bean中吗?我认为,注入类型引用本身也是可以的。

3 个答案:

答案 0 :(得分:1)

这对我有用;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
public class Entity<T> {
    private T data;
    @JsonSerialize(converter = ClassToStringConverter.class)
    @JsonDeserialize(converter = StringToClassConverter.class)
    private Class<T> dataClass;
}

import com.fasterxml.jackson.databind.util.StdConverter;

public class ClassToStringConverter extends StdConverter<Class<?>, String> {

    public String convert(Class<?> aClass) {
//        class java.lang.Integer
        return aClass.toString().split("\\s")[1];
    }
}

import com.fasterxml.jackson.databind.util.StdConverter;

public class StringToClassConverter extends StdConverter<String, Class<?>> {

    public Class<?> convert(String s) {
        try {
            return Class.forName(s);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}

主要;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;

public class Main {

    public static void main(String[] args) throws IOException {
        Entity<Integer> data = new Entity<Integer>();
        data.setData(5);
        data.setDataClass(Integer.class);

        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(data);

        Entity<Integer> jsonData = mapper.readValue(json, new TypeReference<Entity<Integer>>() {});
        System.out.println(jsonData.getData());
        System.out.println(jsonData.getDataClass().getCanonicalName());
    }
}

但是,也许不保存类类型而是使用方法从数据中获取类型会更好吗?

public Class<T> getType() {
    return (Class<T>) data.getClass();
}

答案 1 :(得分:0)

如果不希望将类信息保存在json中并使用@JsonTypeInfo,我建议使用@JacksonInject

  public class Response<T> {
    private T data;
    private double executionDuration;
    private boolean success;
    private String version;

    @JacksonInject("dataClass")
    private Class<T> dataClass;

    public Optional<T> getData() {
      return Optional.ofNullable(data);
    }

    public double getExecutionDuration() {
      return executionDuration;
    }

    public Class<T> getDataClass() {
      return dataClass;
    }

    public String getVersion() {
      return version;
    }

    public boolean isSuccess() {
      return success;
    }
  }

反序列化看起来像:

ObjectMapper mapper = new ObjectMapper();
InjectableValues.Std injectable = new InjectableValues.Std();
injectable.addValue("dataClass", SomeClass.class);
mapper.setInjectableValues(injectable);
final Response<Integer> response = mapper.readValue(json, new TypeReference<Response<SomeClass>>() { });

答案 2 :(得分:0)

public class Response<T> {
    private T data;

    // other fields & methods

    public Class getType() {
        return Optional.ofNullable(data).map(Object::getClass).orElse(Void.class);
    }

    public Optional<Class> getSafeType() {
        return Optional.ofNullable(data).map(Object::getClass);
    }
}

超级简单,无需修补Jackson,NPE安全...