如何使用Jackson ObjectMapper生成不含下划线的JSON键名
问题
从第三方API获取的JSON键名带下划线且无法修改,但希望在POJO中使用无下划线的属性名。目前将Magazine对象转回JSON时仍会出现下划线,需要实现:输出的JSON键名不含下划线,同时保留POJO中无下划线的属性名(如name而非_name)。
原JSON示例
{ "_name": "Vogue", "authors": ["Jenny Mason", "Craig Hall"], "_edition": "plastic-surgery", "_unit_price": "!.75", "_publication_date": "03/22/2023" }
原Jackson ObjectMapper配置
public ObjectMapper initMapper(){ ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule()); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); mapper.enable(SerializationFeature.INDENT_OUTPUT); return mapper; }
原Magazine类代码
import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.util.List; @Data public class Magazine { @JsonProperty("name") private String _name; @JsonProperty("authors") private List<String> _authors; @JsonProperty("unitPrice") private String _unitPrice; @JsonProperty("publicationDate") private String _publication_date; @JsonProperty("edition") private String _edition; public Magazine(String _name, List<String> _authors, String _edition, String _unitPrice, String _publication_date) { this._name = _name; this._authors = _authors; this._edition = _edition; this._unitPrice = _unitPrice; this._publication_date = _publication_date; } }
解决方案
原代码的核心问题是@JsonProperty注解的使用逻辑颠倒,且POJO属性命名不符合需求。以下提供两种可行方案:
方案1:修正POJO的注解与属性命名
直接调整@JsonProperty的作用:注解值指定反序列化时(JSON转POJO)对应的带下划线键名,POJO属性用无下划线的命名,这样序列化(POJO转JSON)时就会用属性名作为输出键。
修正后的Magazine类:
import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.util.List; @Data public class Magazine { // 反序列化匹配JSON的"_name",序列化输出"name" @JsonProperty("_name") private String name; // 反序列化匹配JSON的"authors",序列化输出"authors" @JsonProperty("authors") private List<String> authors; // 反序列化匹配JSON的"_unit_price",序列化输出"unitPrice" @JsonProperty("_unit_price") private String unitPrice; // 反序列化匹配JSON的"_publication_date",序列化输出"publicationDate" @JsonProperty("_publication_date") private String publicationDate; // 反序列化匹配JSON的"_edition",序列化输出"edition" @JsonProperty("_edition") private String edition; public Magazine(String name, List<String> authors, String edition, String unitPrice, String publicationDate) { this.name = name; this.authors = authors; this.edition = edition; this.unitPrice = unitPrice; this.publicationDate = publicationDate; } }
方案2:统一配置ObjectMapper命名策略
如果不想给每个属性加注解,可以通过配置ObjectMapper的命名策略,实现全局的下划线键与驼峰属性的映射,序列化时直接输出驼峰键名。
调整后的ObjectMapper配置:
import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.annotation.JsonInclude; public ObjectMapper initMapper(){ ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule()); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); mapper.enable(SerializationFeature.INDENT_OUTPUT); // 自定义命名策略:反序列化时下划线转驼峰,序列化时保持驼峰输出 mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() { @Override public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) { return PropertyNamingStrategies.SNAKE_CASE.nameForField(config, field, defaultName); } @Override public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { return defaultName; } @Override public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { return PropertyNamingStrategies.SNAKE_CASE.nameForSetterMethod(config, method, defaultName); } }); return mapper; }
此时Magazine类可以完全去掉@JsonProperty注解,直接用无下划线的驼峰属性:
import lombok.Data; import java.util.List; @Data public class Magazine { private String name; private List<String> authors; private String unitPrice; private String publicationDate; private String edition; public Magazine(String name, List<String> authors, String edition, String unitPrice, String publicationDate) { this.name = name; this.authors = authors; this.edition = edition; this.unitPrice = unitPrice; this.publicationDate = publicationDate; } }
验证效果
两种方案执行后,Magazine对象序列化输出的JSON都会是无下划线的格式:
{ "name" : "Vogue", "authors" : [ "Jenny Mason", "Craig Hall" ], "unitPrice" : "!.75", "publicationDate" : "03/22/2023", "edition" : "plastic-surgery" }
内容的提问来源于stack exchange,提问作者BreenDeen
相关产品推荐
相关产品推荐

