将文本动态附加到 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模块