Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
352 views
in Technique[技术] by (71.8m points)

java - Jackson Generics with variable JsonProperty (usage with generics)

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...