【发布时间】:2015-04-10 17:42:02
【问题描述】:
我要做的是:给定一个 JSON 文档,使用 Jackson 将其映射到 POJO,但根据 JSON 文档中的字段定义 Generic 类成员的类型。
我的 JSON 如下所示
{
"name": "Name",
"parameters": [
{"name": "paramName","value": "Value1", "@type": "string"},
{"name": "size","value": 5,"@type": "double"}
]
}
映射到这个 JSON 文档的类是
public class Strategy {
public String name;
public List<Parameter<?>> parameters;
}
然后我有一个通用类,如下所示
public class Parameter<T> {
public String name;
public T value;
@Override
public String toString() {
return this.getClass().getName();
}
}
所以想法是告诉Jackson当你将JSON文档反序列化为Strategy类并进入参数字段时,使用以下类作为值成员的Generic数据类型,即我想选择它为String或 Double 或 Integer,但我希望这是我的决定,以便它是通用的并且可以扩展到我想要的任何数据类型。
我意识到我可以像这样使用我添加的注释 JsonTypeInfo
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="@type")
但是按原样使用这些类实际上是可行的,但是 Jackson 根据其值自行决定类型应该是什么,并且我的 size 参数设置为 Integer。如果我将其值设置为 5.0,则将其设置为可以工作的 Double,但是如果我希望其中一个参数成为自定义对象怎么办?
我可以让它工作的唯一方法(并且对解决方案不是 100% 满意)是使 Parameter 类抽象,然后为我想要的每种类型创建具体类,即 ParameterString、ParameterDouble、ParameterCustomClass 然后使用 @JsonSubTypes 注解根据 JSON 文档中的类型字段设置要使用的正确类。
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="@type")
@JsonSubTypes({
@JsonSubTypes.Type(value=ParameterString.class, name="string"),
@JsonSubTypes.Type(value=ParameterDouble.class, name="double"),
@JsonSubTypes.Type(value=ParameterInstrument.class, name="instrument")
})
以下面的类为例
public class StrategyParameterString extends StrategyParameter<String> {
}
这不是很可扩展,我想它只需要为我需要的每种类型添加一个新的子类型注释和具体类,但感觉不像它应该的那样优雅。
有人知道更好的处理方法吗?
谢谢 安德鲁
【问题讨论】:
-
我只是好奇你为什么要这样做。 Java 通过擦除实现泛型类型。这意味着泛型类型参数存在并且仅在编译时才有意义。它们在运行时不存在。您的
List<Parameter<?>>的运行时class对象是List.class。如果您需要将类型信息与不可具体化的类型相关联,我建议您创建一个类型安全的异构容器并将其存储在您的 List 中,例如List<MyHeterogenousContainer>. -
感谢您的 cmets @scottb。基本上我通过最初为我需要的每种类型创建一个类,让它们实现一个接口并让我的 List
达到这一点,那里有两个问题,首先当我遍历列表时,对象不知道任何关于类成员,除非我强制转换它,其次每个类都有重复的代码,所以我将它重构为一个基本抽象类以减少代码重复。我想具体的类实现会在编译时设置类型,因此由于 Java 擦除,这可能是一种更好的处理方式。
标签: java json generics jackson