我有一个像这样的java类:
class TestJsonClass {
private String propertyA;
private String propertyB;
private String propertyC;
}
现在在运行时我想为每个属性提供不同的属性名称,而不是使用 @JsonProperty("sample") 的静态名称
我该如何做到这一点?我正在使用杰克逊图书馆广告 Spring MVC
提前致谢...
我有一个像这样的java类:
class TestJsonClass {
private String propertyA;
private String propertyB;
private String propertyC;
}
现在在运行时我想为每个属性提供不同的属性名称,而不是使用 @JsonProperty("sample") 的静态名称
我该如何做到这一点?我正在使用杰克逊图书馆广告 Spring MVC
提前致谢...
您可以为此目的使用模块。这是解决您的问题的最简单方法。这是一个例子:
一个简单的类,可以为每个请求携带您的属性名称映射:
public class PropertyNameMapper {
// The class for which the mappings need to take place.
public Class<?> classToFilter;
// The mappings property names. Key would be the existing property name
// value would be name you want in the ouput.
public Map<String, String> nameMappings = Collections.emptyMap();
public PropertyNameMapper(Class<?> classToFilter, Map<String, String> nameMappings) {
this.classToFilter = classToFilter;
this.nameMappings = nameMappings;
}
}
一个自定义BeanPropertyWriter,将用于指定属性的输出名称。
public class MyBeanPropertyWriter extends BeanPropertyWriter {
// We would just use the copy-constructor rather than modifying the
// protected properties. This is more in line with the current design
// of the BeanSerializerModifier class (according to its documentation).
protected MyBeanPropertyWriter(BeanPropertyWriter base, String targetName) {
super(base, new SerializedString(targetName));
}
}
现在,每次调用一个自定义BeanSerializerModifier以允许您修改序列化属性。
public class MySerializerModifier extends BeanSerializerModifier {
public List<BeanPropertyWriter> changeProperties(
SerializationConfig config, BeanDescription beanDesc,
List<BeanPropertyWriter> beanProperties) {
List<PropertyNameMapper> propertyMappings = getNameMappingsFromRequest();
PropertyNameMapper mapping = mappingsForClass(propertyMappings,
beanDesc.getBeanClass());
if (mapping == null) {
return beanProperties;
}
List<BeanPropertyWriter> propsToWrite = new ArrayList<BeanPropertyWriter>();
for (BeanPropertyWriter propWriter : beanProperties) {
String propName = propWriter.getName();
String outputName = mapping.nameMappings.get(propName);
if (outputName != null) {
BeanPropertyWriter modifiedWriter = new MyBeanPropertyWriter(
propWriter, outputName);
propsToWrite.add(modifiedWriter);
} else {
propsToWrite.add(propWriter);
}
}
return propsToWrite;
}
private List<PropertyNameMapper> getNameMappingsFromRequest() {
RequestAttributes requestAttribs = RequestContextHolder
.getRequestAttributes();
List<PropertyNameMapper> nameMappings = (List<PropertyNameMapper>) requestAttribs
.getAttribute("nameMappings",
RequestAttributes.SCOPE_REQUEST);
return nameMappings;
}
private PropertyNameMapper mappingsForClass(
List<PropertyNameMapper> nameMappings, Class<?> beanClass) {
for (PropertyNameMapper mapping : nameMappings) {
if (mapping.classToFilter.equals(beanClass)) {
return mapping;
}
}
return null;
}
}
现在,您需要一个自定义模块才能使用上面创建的BeanSerializerModifier自定义输出:
public class MyModule extends Module {
@Override
public String getModuleName() {
return "Test Module";
}
@Override
public void setupModule(SetupContext context) {
context.addBeanSerializerModifier(new MySerializerModifier());
}
@Override
public Version version() {
// Modify if you need to.
return Version.unknownVersion();
}
}
现在用你的ObjectMapper注册这个模块。您可以从 spring 应用程序上下文中获取 Jackson HTTP 消息转换器,并获取其对象映射器。
// Figure out a way to get the ObjectMapper.
MappingJackson2HttpMessageConverter converter = ... // get the jackson-mapper;
converter.getObjectMapper().registerModule(new MyModule())
就是这样。这是动态自定义属性序列化的最简单方法。
要使用它,请创建一个List
ofPropertyNameMappers
并将其添加为当前请求中的属性(在此示例中名为“nameMappings”)。
这是一个示例,不是生产就绪代码。您可能需要添加空检查和类似的东西。此外,根据您使用的库版本,可能需要进行一些小的调整。
如果解决方案对您不起作用,请告诉我您面临的问题。
您可以将自定义 PropertyNamingStrategy 注入反序列化中使用的 ObjectMapper。
只需在运行时将字段设置到 PropertyNamingStrategy,假设您可以将它们映射到默认的 JsonPropertyName 之类的东西(例如 propertyA、propertyB、propertyC)。
public class MyNamingStrategy extends PropertyNamingStrategy {
String propertyAName, propertyBName, propertyCName;
public MyNamingStrategy(String propANm, String propBNm, String propCNm) {
this.propertyAName = propANm;
//finish
}
@Override
public String nameForField(MapperConfig<?> config, AnnotatedField field,
String defaultName) {
return convert(defaultName);
}
@Override
public String nameForGetterMethod(MapperConfig<?> config,
AnnotatedMethod method, String defaultName) {
return convert(defaultName);
}
@Override
public String nameForSetterMethod(MapperConfig<?> config,
AnnotatedMethod method, String defaultName) {
return convert(defaultName);
}
public String convert(String defaultName ){
return defaultName.replace("propertyA", propertyAName).replace( //finish
}
最后,您将创建一个实例并在运行时注入它。objectMapper.setNamingStrategy(myNamingStrategyInstance));
有关 PropertyNamingStrategy 的更多信息,请参阅此 Cowtowncoder 帖子:
或者这个文档:
github.com/FasterXML/jackson-docs/wiki/PropertyNamingStrategy