当前位置: 首页 > 知识库问答 >
问题:

Jackson如何在searlization过程中添加其他属性,而不更改默认POJO?

方风华
2023-03-14

我正在使用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,但不想将新字段工作和公司添加到我的CustomClassPOJO。

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

我试着这样做:https://www.jdoodle.com/a/z99但是我得到了一个错误:Type-id处理没有为Type-package实现。ClassName(按package.CustomModule$CustomClassSerializer类型的序列化程序

共有1个答案

李华茂
2023-03-14

您可以在控制器级别尝试以下操作(最好使用拦截器或过滤器来操纵响应)

   @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);
    
        }

输出:{“姓名”:“蝙蝠侠”,“年龄”:30,“工作”:“人力资源”,“公司”:“新”}

更新

但我得到了一个错误:没有为类型包实现类型id处理。ClassName(按package.CustomModule$CustomClassSerializer类型的序列化程序)

将新的对象字段“job”和“company”写入自定义类序列化程序。

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();
            }
        }
    }
}

输出:{“姓名”:“蝙蝠侠”,“年龄”:30,“工作”:“人力资源”,“公司”:“新”}

 类似资料:
  • 问题内容: 我通常将文字设置为粗体(或斜体或其他字体属性) 如何仅删除粗体属性,而不更改到目前为止可能已设置的其他属性? 问题答案: 这会将样式设置为正常,而不会更改颜色或大小。 但是您不能以这种方式混合使用粗体/斜体/下划线文本。如果指定粗体,则所有文本均将为粗体。如果要混合文本样式,建议使用HTML设置文本样式,然后使用以下代码。

  • 我试图找到一种方法,为通过注释从Spring Boot中的application.property文件访问的属性设置UTF-8编码。到目前为止,我已经通过创建一个bean成功地将编码设置到我自己的属性源: 这样的解决方案存在两个问题。这一次,它与Spring Boot默认使用的“application.properties”位置(http://docs.Spring.io/spring-boot/

  • 问题内容: 内容: 我要从更改为。这是我的代码: 输出内容: 其他属性将被删除。我想更新一个特定的属性值,而不删除其他属性。 问题答案: 关闭输入流后,打开输出流并存储属性。

  • 问题内容: 这是我当前的SQL的样子: 这是我的数据库_users表的样子: 我收到此错误: 您的SQL语法有误;检查与您的MariaDB服务器版本相对应的手册,以在’rid_in附近使用正确的语法;-修改列的默认值 链接到此行: 如果我更改此设置,则忽略该值: 它工作正常,如何将输入绑定到查询? 我的预期输出是能够用来更改默认用户角色值并将具有旧用户值的所有行更新为新行: 为了能够更新每个用户的

  • 问题内容: 我修改了一个表格,以这种方式向其中添加状态列 但是,对于创建的任何新ITEM,SQLite似乎都不会将N添加到该列中。语法是否错误,或者SQLite及其对默认值的支持是否存在任何问题。 我正在使用SQLite 3.6.22 问题答案: 对我来说看上去很好。 这是文档。 转储您的模式,并 在调用ALTER TABLE之后但在INSERT之前 验证 表结构是否存在。如果它在事务中,请 确保

  • 问题内容: 我有两个实体,消息和用户。用户与消息有一个ManyToMany关系(一个用户可以有多个消息),而消息(现在,为了使其不那么复杂)与用户有一个ManyToMany关系(可以将一条消息发送给多个用户)。 我正在使用@JoinTable加入这两个实体,但是,我想在连接表中添加一个“状态”列,以告知该消息是否是新消息,已读消息等。我当时正在考虑将该列放入Message实体中,但是,我认为这可能