杰克逊泛型与变量JsonProperty(用泛型) [英] Jackson Generics with variable JsonProperty (usage with generics)

查看:348
本文介绍了杰克逊泛型与变量JsonProperty(用泛型)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  public class Data< U> {

@JsonProperty(困难)
私人U []数据;

// ... geter setter构造函数
}

我不想创建10个更类似的类,因为我只需要更改一行代码(在这种情况下@JsonProperty(困难))。属性值取决于类型。是否可以在一个类中编写它?

解决方案

基于MichałZiober在这里我能够改变默认值字段名称通过重写PropertyNamingStrategy值


这些是我收到的JSON示例(简化版):

  {status:OK,error:null,data:{
困难:[{value:easy},{ value:medium}]
}}

{status:ok,error:null,data:{
countries :[{code:AT},{code:BE}]
}}

查看第二行的差异,其中数据对象包含难度
或国家(或许多其他基于上下文的名称)。

基于JSON响应的响应类:

  public class Response< T> {
private String status;
私有字符串错误;
私人资料< T>数据;
// Getters Setters构造函数
}

基于JSON响应的数据类:

  public class Data< T> {
//属性名称,将被更改
@JsonProperty(DataNamingStrategy.DATA_FIELD)
private T [] data;
// Getters Setters构造函数
}

这是命名策略,将默认值更改为运行时指定值

  public class DataNamingStrategy extends PropertyNamingStrategy {

//由其他类(这将是应该更改的默认字段名称)
public static final String DATA_FIELD =variable:data;
private String fieldName;

public DataNamingStrategy(String fieldName){
this.fieldName = fieldName;
}

//在这种情况下,使用它来改变不需要的字段名称(格式variable:value)
@Override
public String nameForField MapperConfig<?> config,AnnotatedField field,
String defaultName){
return(defaultName.equals(DATA_FIELD))?
fieldName:
super.nameForField(config,field,defaultName);
}

//使用它来更改setter方法字段名称(JSON - >格式为variable的对象:{})
@Override
public String nameForSetterMethod(MapperConfig<?> config,
AnnotatedMethod方法,String defaultName){
return(defaultName.equals(DATA_FIELD))?
fieldName:
super.nameForGetterMethod(config,method,defaultName);
}

//使用它来改变getter方法字段名称(Object - >格式为variable的JSON:{})
//应该和nameForSetterMethod相同
@Override
public String nameForGetterMethod(MapperConfig<?> config,
AnnotatedMethod method,String defaultName){
return nameForSetterMethod(config,method,defaultName);
}
}

使用应该如下所示:

  ObjectMapper mapper = new ObjectMapper(); 
mapper.setPropertyNamingStrategy(new DataNamingStrategy(tableName));
JavaType type = mapper.getTypeFactory()。constructParametricType(Response.class,dataClass);
回应< U> u = mapper.readValue(result,type);

其中 result 是Json as String, code> tableName 是将用于JSON而不是默认值的字符串, dataClass U的类(例如Difficulty.class)。



更好地使用 PropertyNamingStrategy 应该是 Map 而不是一个字符串。但我只需要改变一个特定的值。



另请参阅 PropertyNamingStrategy 文档或在米奇尔齐奥贝的回答


I have class that looks like this:

public class Data<U> {

    @JsonProperty("difficulties")
    private U[] data;

    // ... geter setter constructor
}

And I don't want to create 10 more similar classes just because I need to change only one line of code (@JsonProperty("difficulties") in this case). The property value depends on Type. Is it possible to write it in one class?

解决方案

Based on response of Jackson - Modify an attribute at runtime without annotation by Michał Ziober here I was able to change default field name values by overriding PropertyNamingStrategy:

These are my received JSON examples (simplified):

{"status": "OK","error": null,"data": {
    "difficulties": [{"value":"easy"},{"value":"medium"}]
}}

{"status": "ok", "error": null, "data": {
    "countries": [{"code": "AT"},{"code": "BE"}]
}}

see the difference in second line where data object contains either difficulties or countries (or many other names based on context).

Response class based on JSON response:

public class Response<T>{
    private String status;
    private String error;
    private Data<T> data;
    // Getters Setters Constructors
}

Data class based on JSON response:

public class Data<T> {
    // property name, that will be changed
    @JsonProperty(DataNamingStrategy.DATA_FIELD)
    private T[] data;
    // Getters Setters Constructors
}

And this is Naming strategy, that changes default value to runtime specified value

public class DataNamingStrategy extends PropertyNamingStrategy{

    // used by other classes (this will be default field name that should be changed)
    public static final String DATA_FIELD = "variable:data";
    private String fieldName;

    public DataNamingStrategy(String fieldName) {
        this.fieldName = fieldName;
    }

    // use this to change field name (format "variable":"value") not needed in my case
    @Override
    public String nameForField(MapperConfig<?> config, AnnotatedField field,
            String defaultName) {
        return (defaultName.equals(DATA_FIELD))?
            fieldName :
            super.nameForField(config, field, defaultName);
    }

    // use this to change setter method field name (JSON -> Object with format "variable":{})
    @Override
    public String nameForSetterMethod(MapperConfig<?> config,
            AnnotatedMethod method, String defaultName) {
        return (defaultName.equals(DATA_FIELD))?
            fieldName :
            super.nameForGetterMethod(config, method, defaultName);
    }

    // use this to change getter method field name (Object -> JSON with format "variable":{})
    // should be same as nameForSetterMethod
    @Override
    public String nameForGetterMethod(MapperConfig<?> config,
            AnnotatedMethod method, String defaultName) {
        return nameForSetterMethod(config, method, defaultName);
    }
}

And usage should look like this:

ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new DataNamingStrategy(tableName));
JavaType type = mapper.getTypeFactory().constructParametricType(Response.class, dataClass);
Response<U> u = mapper.readValue(result, type);

Where result is Json as String, tableName is String that will be used in JSON instead of default value and dataClass is class for U (for example Difficulty.class).

Better usage of PropertyNamingStrategy should be Map instead of one String. But I just needed to change one particular value.

Also have a look at PropertyNamingStrategy documentation or again at Michał Ziober's answer

这篇关于杰克逊泛型与变量JsonProperty(用泛型)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆