如何让Jackson的@JsonProperty支持枚举值作为属性参数?
Since Jackson's @JsonProperty requires a compile-time constant (and your enum's value isn't one), you have two clean, maintainable solutions that let you map the dynamic JSON key to your DTO's frequency field without hardcoding the string. Both options ensure that when ParameterList.FREQUENCY_ID's value changes, you only need to update the enum—no changes to the DTO are required.
Option 1: Use @JsonAnySetter (and @JsonAnyGetter for serialization)
This is the simplest approach, especially if you only need to handle this one dynamic field. The @JsonAnySetter annotation catches any JSON keys that don't match a DTO field, letting you route them to the correct property using your enum.
DTO Code:
import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonAnyGetter; import java.util.HashMap; import java.util.Map; public class YourDto { private String frequency; // Standard getter/setter for frequency public String getFrequency() { return frequency; } public void setFrequency(String frequency) { this.frequency = frequency; } // Handle dynamic JSON keys @JsonAnySetter public void handleDynamicProperty(String key, String value) { if (ParameterList.FREQUENCY_ID.toString().equals(key)) { this.frequency = value; } // Add else-if blocks here for other dynamic fields if needed } // Optional: For serializing back to JSON with the dynamic key @JsonAnyGetter public Map<String, String> getDynamicProperties() { Map<String, String> dynamicProps = new HashMap<>(); if (frequency != null) { dynamicProps.put(ParameterList.FREQUENCY_ID.toString(), frequency); } return dynamicProps; } }
How it works:
- When deserializing, Jackson calls
handleDynamicPropertywith the "500" key and "100Hz" value. The method checks if the key matches your enum's value and sets thefrequencyfield accordingly. - When serializing,
getDynamicPropertiesadds the enum's value as the key and thefrequencyvalue to the output JSON.
Option 2: Custom DTO Deserializer
If you need more control over deserialization (e.g., handling multiple complex dynamic fields), create a custom deserializer that explicitly looks up the enum's key in the JSON.
Step 1: Create the Deserializer
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; public class YourDtoDeserializer extends StdDeserializer<YourDto> { protected YourDtoDeserializer() { super(YourDto.class); } @Override public YourDto deserialize(JsonParser parser, DeserializationContext context) throws IOException { JsonNode rootNode = parser.getCodec().readTree(parser); YourDto dto = new YourDto(); // Get the dynamic key from your enum String frequencyKey = ParameterList.FREQUENCY_ID.toString(); if (rootNode.has(frequencyKey)) { dto.setFrequency(rootNode.get(frequencyKey).asText()); } // Add code here to deserialize other DTO fields normally // Example: if (rootNode.has("otherField")) { dto.setOtherField(rootNode.get("otherField").asText()); } return dto; } }
Step 2: Attach the Deserializer to Your DTO
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @JsonDeserialize(using = YourDtoDeserializer.class) public class YourDto { private String frequency; // Standard getter/setter for frequency public String getFrequency() { return frequency; } public void setFrequency(String frequency) { this.frequency = frequency; } // Other fields and their getters/setters }
How it works:
- The deserializer reads the entire JSON tree, looks for the key matching your enum's value, and maps its value to the
frequencyfield. - You can extend this to handle additional dynamic fields or custom validation logic easily.
Both solutions keep your code DRY and maintainable—any future changes to ParameterList.FREQUENCY_ID's value will automatically reflect in the JSON mapping without touching the DTO code.
内容的提问来源于stack exchange,提问作者htshame

