Java 您可以重命名泛型类中的变量吗?
我有一个类Java 您可以重命名泛型类中的变量吗?,java,json,generics,Java,Json,Generics,我有一个类PagedResult。这个类是用来帮助我实现一个JSON输出,它以页面格式包含不同的对象。E是包装在列表中的对象。这一切都很好,但有一件事仍然困扰着我。我希望包含对象的列表不总是具有相同的名称。我想使名称适应相应的对象 类PagedResult: public class PagedResult<E> { Long totalItems; Integer totalPages; Integer currentPage; List<E> elements;
PagedResult
。这个类是用来帮助我实现一个JSON输出,它以页面格式包含不同的对象。E
是包装在列表中的对象。这一切都很好,但有一件事仍然困扰着我。我希望包含对象的列表不总是具有相同的名称。我想使名称适应相应的对象
类PagedResult
:
public class PagedResult<E> {
Long totalItems;
Integer totalPages;
Integer currentPage;
List<E> elements;
[... Getter & Setter ...]
}
因此,对于每个响应,无论是哪个对象,数组都被命名为“elements”。我不想在JSON响应中使用难看的名称,因为PagedResult
-类中的对象不断变化。当我用MyPojo
这样的对象得到响应时,JSON数组的名称应该是“myPojos”,当我想用MyWin
这样的对象得到响应时,名称应该是“myWins”
我用
@JsonProperty
做了很多尝试,但我找不到一种方法来实现这个同样通用的“对象数组名”。有人能帮我解决这个问题吗?提前谢谢。不,你不能那样做。泛型类型具有类型参数,而不是标识符参数。另外,Java语言中没有任何东西允许您在生成类型时将Java标识符作为参数。(当然,在这种情况下,您不能使用任何东西!)
备选方案:
- 不要这样做。(仔细看看您希望JSON属性名称变化的原因。它实际上实现了什么?值得付出努力吗?)
- 不要使用泛型类型。为每种“分页结果”定义不同的类。(笨重,不推荐。)
- 使用映射,并为每种“分页结果”的元素属性填充不同的映射键。(缺点是您会丢失静态类型检查,并会对性能和存储造成较小的损失。但这些损失不太可能很大。)
- 编写一个自定义映射程序,根据您的要求序列化和反序列化
PagedResult
就其价值而言,标识符作为参数是您可以使用宏预处理器来做的事情。那种Java语言没有对这种事情的标准支持。不,你不能这样做。泛型类型具有类型参数,而不是标识符参数。另外,Java语言中没有任何东西允许您在生成类型时将Java标识符作为参数。(当然,在这种情况下,您不能使用任何东西!) 备选方案:
- 不要这样做。(仔细看看您希望JSON属性名称变化的原因。它实际上实现了什么?值得付出努力吗?)
- 不要使用泛型类型。为每种“分页结果”定义不同的类。(笨重,不推荐。)
- 使用映射,并为每种“分页结果”的元素属性填充不同的映射键。(缺点是您会丢失静态类型检查,并会对性能和存储造成较小的损失。但这些损失不太可能很大。)
- 编写一个自定义映射程序,根据您的要求序列化和反序列化
PagedResult
就其价值而言,标识符作为参数是您可以使用宏预处理器来做的事情。该Java语言没有对此类内容的标准支持。是的,可以使用自定义序列化程序。但即使使用自定义序列化程序,您仍然存在一个问题:泛型在编译时被删除。因此,我们需要在运行时以某种方式获取类型 下面是一个示例,它只检查
elements
列表中第一个元素的类型。这显然不是最干净的方法,但您不必调整PagedResult
类
public class PagedResultSerializer<T> extends JsonSerializer<PagedResult<Object>> {
@Override
public void serialize(PagedResult<Object> value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeNumberField("totalItems", value.getTotalItems());
// Your other attributes
if (!value.getElements().isEmpty()) {
Object firstElement = value.getElements().get(0);
String elementsFieldName;
if (firstElement instanceof MyPojo) {
elementsFieldName = "myPojos";
} else if (firstElement instanceof MyWin) {
elementsFieldName = "myWins";
} else {
throw new IllegalArumentException("Unknown type");
}
serializers.defaultSerializeField(elementsFieldName, value.getElements(), gen);
}
gen.writeEndObject();
}
}
公共类PagedResultSerializer扩展JsonSerializer{
@凌驾
public void serialize(PagedResult值、JsonGenerator gen、SerializerProvider提供程序)引发IOException{
gen.writeStartObject();
gen.writeNumberField(“totalItems”,value.getTotalItems());
//你的其他属性
如果(!value.getElements().isEmpty()){
Object firstElement=value.getElements().get(0);
字符串元素字段名;
if(MyPojo的第一个元素实例){
elementsFieldName=“myPojos”;
}else if(MyWin的第一个元素实例){
elementsFieldName=“myWins”;
}否则{
抛出新的IllegalRumentException(“未知类型”);
}
serializers.defaultSerializeField(elementsFieldName,value.getElements(),gen);
}
writeEndObject将军();
}
}
现在你只需要告诉Jackson使用这个序列化程序而不是默认的
@JsonSerialize(using = PagedResultSerializer.class)
public class PagedResult<T> {
// Your code
}
@JsonSerialize(使用=PagedResultSerializer.class)
公共类PagedResult{
//你的代码
}
改进:向您的
PagedResult
添加Class elementsType
属性,并在序列化程序中使用此属性,而不是检查列表中的第一个元素。是的,可以使用自定义序列化程序。但即使使用自定义序列化程序,您仍然存在一个问题:泛型在编译时被删除。因此,我们需要在运行时以某种方式获取类型
下面是一个示例,它只检查elements
列表中第一个元素的类型。这显然不是最干净的方法,但您不必调整PagedResult
类
public class PagedResultSerializer<T> extends JsonSerializer<PagedResult<Object>> {
@Override
public void serialize(PagedResult<Object> value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeNumberField("totalItems", value.getTotalItems());
// Your other attributes
if (!value.getElements().isEmpty()) {
Object firstElement = value.getElements().get(0);
String elementsFieldName;
if (firstElement instanceof MyPojo) {
elementsFieldName = "myPojos";
} else if (firstElement instanceof MyWin) {
elementsFieldName = "myWins";
} else {
throw new IllegalArumentException("Unknown type");
}
serializers.defaultSerializeField(elementsFieldName, value.getElements(), gen);
}
gen.writeEndObject();
}
}
公共类PagedResultSerializer扩展JsonSerializer{
@凌驾
public void serialize(PagedResult值、JsonGenerator gen、SerializerProvider提供程序)引发IOException{
gen.writeStartObject();
gen.writeNumberField(“totalItems”,value.getTotalItems());
//你的ot