Jackson 如何在不更改默认 POJO 的情况下在序列化期间添加其他属性?

Jackson How to add additional properties during searlization without making changes to default POJO?

我正在使用 Jackson-ObjectMapper 根据我的 POJO 创建 JSON 数据。我想在不修改 POJO 的情况下向 JSON 添加一些额外的属性。

由于 POJO 已作为依赖项添加到我的项目中,我无法修改它,但我需要 JSON 中的一些附加字段。有没有办法在不修改 Java POJO 的情况下向 JSON 添加新的键值对?我目前使用的是 Jackson 2.13.2 最新版本依赖:jackson-core, jackson-databind, jackson-annotations, jackson-datatype-jdk8

以下是Java代码:

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.Setter;

public class Test {
    public static void main(String args[]) throws Exception{
        ObjectMapper objectMapper = new ObjectMapper();

        CustomClass cc = new CustomClass();
        cc.setName("Batman");
        cc.setAge(30);
        System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(cc));
    }

    @Getter
    @Setter
    public static class CustomClass {
        private String name;
        private int age;
    }
}

这为我提供了 JSON:

{
  "name" : "Batman",
  "age" : 30
}

我想获得看起来像这样的 JSON,但不想向我的 CustomClass POJO 添加新的字段工作和公司。

{
  "name" : "Batman",
  "age" : 30,
  "job" : "HR",
  "company": "New"
}

我试图做这样的事情:https://www.jdoodle.com/a/z99 但我收到错误:Type id handling not implemented for type package.ClassName (by serializer of type package.CustomModule$CustomClassSerializer)

你可以在controller级别尝试如下,(最好使用Interceptor或Filter来操纵响应)

   @GetMapping
   public ObjectNode test() throws JsonProcessingException {

    CustomClass customClass = new CustomClass();
    customClass.setAge(30);
    customClass.setName("Batman");

    ObjectMapper mapper = new ObjectMapper();
    String jsonStr = mapper.writeValueAsString(customClass);
    ObjectNode nodes = mapper.readValue(jsonStr, ObjectNode.class);
    nodes.put("job", "HR ");
    nodes.put("company", "New ");

    return nodes;
}

响应:

{
name: "Batman",
age: 30,
job: "HR ",
company: "New "
}

你的新试驾如下,

 public static void main(String[] args) throws JsonProcessingException {
            CustomClass customClass = new CustomClass();
            customClass.setAge(30);
            customClass.setName("Batman");
    
            ObjectMapper mapper = new ObjectMapper();
            String jsonStr = mapper.writeValueAsString(customClass);
            ObjectNode nodes = mapper.readValue(jsonStr, ObjectNode.class);
            nodes.put("job", "HR ");
            nodes.put("company", "New ");
            System.out.println(nodes);
    
        }

输出: {"name":"Batman","age":30,"job":"HR ","company":"New "}


已更新

but I get the error: Type id handling not implemented for type package.ClassName (by serializer of type package.CustomModule$CustomClassSerializer)

将新对象字段“工作”和“公司”写入您的自定义 class 序列化程序。

public class Test {
    public static void main(String args[]) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new CustomModule());
        CustomClass cc = new CustomClass();
        cc.setAge(30);
        cc.setName("Batman");
        StringWriter sw = new StringWriter();
        objectMapper.writeValue(sw, cc);
        System.out.println(sw.toString());
    }

    public static class CustomModule extends SimpleModule {
        public CustomModule() {
            addSerializer(CustomClass.class, new CustomClassSerializer());
        }

        private static class CustomClassSerializer extends JsonSerializer {
            @Override
            public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
                // Validate.isInstanceOf(CustomClass.class, value);
                jgen.writeStartObject();
                JavaType javaType = provider.constructType(CustomClass.class);
                BeanDescription beanDesc = provider.getConfig().introspect(javaType);
                JsonSerializer<Object> serializer = BeanSerializerFactory.instance.findBeanSerializer(provider,
                        javaType, beanDesc);
                // this is basically your 'writeAllFields()'-method:
                serializer.unwrappingSerializer(null).serialize(value, jgen, provider);
                jgen.writeObjectField("job", "HR ");
                jgen.writeObjectField("company", "New ");
                jgen.writeEndObject();
            }
        }
    }
}

输出: {"name":"Batman","age":30,"job":"HR ","company":"New "}