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

Time:05-03

I am using Jackson-ObjectMapper to create the JSON data according to my POJO. I would like to add some additional properties to my JSON without modifying the POJO.

Since the POJO has been added as a dependency in my project I cannot modify it but I need some additional fields in JSON. Is there a way to add new key-value pair to JSON without making modifications to Java POJO? I am currently using Jackson 2.13.2 latest version dependencies: jackson-core, jackson-databind, jackson-annotations, jackson-datatype-jdk8

Following is the Java code:

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

This is providing me with the JSON:

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

I would like to obtain the JSON that looks something like this, but do not want to add new fields job and company to my CustomClass POJO.

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

I tried to do something like this: https://www.jdoodle.com/a/z99 but I get the error: Type id handling not implemented for type package.ClassName (by serializer of type package.CustomModule$CustomClassSerializer)

CodePudding user response:

You can try like below in the controller level, (it would be better to manipulate the response by using the Interceptor or 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;
}

Response:

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

Your new test driver is below,

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

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


Updated

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

Write new object fields "job" and "company" to your custom class serializer.

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

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

  • Related