将文本动态附加到 Jackson 中任何对象的所有 属性 名称
Dynamically appending text to all property names of any object in Jackson
考虑以下对象
@Value
public class Example {
@JsonProperty("StrValue")
String strValue;
@JsonProperty("Internal")
Internal internal;
@Value
public static class Internal {
@JsonProperty("InternalValue")
String internalValue;
}
}
我可以获得此对象的序列化,例如
"Example" : {
"StrValue": "v1",
"Internal": {
"InternalValue": "v2"
}
}
但是,我需要这个对象的两个不同版本,一个是将字符串 First
附加到所有属性的名称,另一个是 Second
:
"ExampleFirst" : {
"StrValueFirst": "v1",
"InternalFirst": {
"InternalValueFirst": "v2"
}
}
(Second
也类似)
请注意,这应该适用于嵌套属性和任何 class 的任何对象。是否有捷径可寻?我觉得这可能是 BeanSerializerModifier
或其他一些自定义序列化机制的工作,但是,自定义序列化 API 非常低级并且文档很少。
回答我自己的问题,因为我(有点)解决了它:
首先我会创建一个 BeanPropertyWriter
的子类,例如
class AppendingPropertyWriter extends BeanPropertyWriter {
private final BeanPropertyWriter writer;
public AppendingPropertyWriter(BeanPropertyWriter writer) {
super(writer);
this.writer = writer;
}
@Override
public void serializeAsField(Object bean,
JsonGenerator gen,
SerializerProvider prov) throws Exception {
Object value = writer.get(bean);
gen.writeObjectField(writer.getName() + "First", value);
}
}
然后将其添加到 BeanSerializerModifier
中:
public class AppendingSerializerModifier extends BeanSerializerModifier {
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
for (int i = 0; i < beanProperties.size(); i++) {
BeanPropertyWriter writer = beanProperties.get(i);
beanProperties.set(i, new AppendingPropertyWriter(writer));
}
return beanProperties;
}
}
然后你必须把它放到你的 ObjectMapper
中,比如:
var serializerModifier = new AppendingSerializerModifier();
var sf = BeanSerializerFactory.instance.withSerializerModifier(serializerModifier);
ObjectMapper mapper = new XmlMapper();
mapper.setSerializerFactory(sf);
那么这个mapper就达到了预期的效果。然而,这似乎绕过了我添加的一些其他模块,如 JavaTimeModule
并抛出异常。因此,如果有人对此有解决方案,我将不胜感激。
编辑:已修复!结果我需要将对象序列化为
@Override
public void serializeAsField(Object bean,
JsonGenerator gen,
SerializerProvider prov) throws Exception {
Object value = writer.get(bean);
prov.defaultSerializeField(writer.getName() + "First", value, gen);
}
然后一定要在设置出厂后注册JavaTime
模块
考虑以下对象
@Value
public class Example {
@JsonProperty("StrValue")
String strValue;
@JsonProperty("Internal")
Internal internal;
@Value
public static class Internal {
@JsonProperty("InternalValue")
String internalValue;
}
}
我可以获得此对象的序列化,例如
"Example" : {
"StrValue": "v1",
"Internal": {
"InternalValue": "v2"
}
}
但是,我需要这个对象的两个不同版本,一个是将字符串 First
附加到所有属性的名称,另一个是 Second
:
"ExampleFirst" : {
"StrValueFirst": "v1",
"InternalFirst": {
"InternalValueFirst": "v2"
}
}
(Second
也类似)
请注意,这应该适用于嵌套属性和任何 class 的任何对象。是否有捷径可寻?我觉得这可能是 BeanSerializerModifier
或其他一些自定义序列化机制的工作,但是,自定义序列化 API 非常低级并且文档很少。
回答我自己的问题,因为我(有点)解决了它:
首先我会创建一个 BeanPropertyWriter
的子类,例如
class AppendingPropertyWriter extends BeanPropertyWriter {
private final BeanPropertyWriter writer;
public AppendingPropertyWriter(BeanPropertyWriter writer) {
super(writer);
this.writer = writer;
}
@Override
public void serializeAsField(Object bean,
JsonGenerator gen,
SerializerProvider prov) throws Exception {
Object value = writer.get(bean);
gen.writeObjectField(writer.getName() + "First", value);
}
}
然后将其添加到 BeanSerializerModifier
中:
public class AppendingSerializerModifier extends BeanSerializerModifier {
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
for (int i = 0; i < beanProperties.size(); i++) {
BeanPropertyWriter writer = beanProperties.get(i);
beanProperties.set(i, new AppendingPropertyWriter(writer));
}
return beanProperties;
}
}
然后你必须把它放到你的 ObjectMapper
中,比如:
var serializerModifier = new AppendingSerializerModifier();
var sf = BeanSerializerFactory.instance.withSerializerModifier(serializerModifier);
ObjectMapper mapper = new XmlMapper();
mapper.setSerializerFactory(sf);
那么这个mapper就达到了预期的效果。然而,这似乎绕过了我添加的一些其他模块,如 JavaTimeModule
并抛出异常。因此,如果有人对此有解决方案,我将不胜感激。
编辑:已修复!结果我需要将对象序列化为
@Override
public void serializeAsField(Object bean,
JsonGenerator gen,
SerializerProvider prov) throws Exception {
Object value = writer.get(bean);
prov.defaultSerializeField(writer.getName() + "First", value, gen);
}
然后一定要在设置出厂后注册JavaTime
模块