1

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)

BATMAN_2008
  • 2,788
  • 3
  • 31
  • 98
  • You can serialize the object to an intermediate JSON object buffer (`ObjectNode` in Jackson if I'm not mistaken), and manipulate its contents. Or, if not buffering, it's also possible to intercept the output stream and write directly to the stream (not sure how easy it is in Jackson, but definitely possible). Or, if I understand what Jackson mixins are, Jackson mixins can also help you. – terrorrussia-keeps-killing May 02 '22 at 14:45
  • @terrorrussia-keeps-killing Thanks a lot for your response. I have posted my code sample here: https://stackoverflow.com/q/72089765/7584240 with this code I am getting the above mentioned error, can you please once have a look and provide some response? – BATMAN_2008 May 02 '22 at 18:00

1 Answers1

1

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

Sibin Rasiya
  • 1,132
  • 1
  • 11
  • 15
  • Thanks a lot for your response. I am getting following error when I am adding the code: `Type id handling not implemented for type package.ClassName (by serializer of type package.CustomModule$CustomClassSerializer)` how to fix this? – BATMAN_2008 May 02 '22 at 15:42
  • Because you missed the field "job" and "company" while writing, I updated the answer. Please check. – Sibin Rasiya May 02 '22 at 15:56
  • Actually, when running for the sample project it's working when I try to integrate the same to my real project I get the error: `Type id handling not implemented for type package.ClassName (by serializer of type package.CustomModule$CustomClassSerializer)` – BATMAN_2008 May 02 '22 at 16:05
  • Actually, you missed mentioning the above phrases while asking the question. But the above pieces of stuff should answer the question you asked. – Sibin Rasiya May 02 '22 at 16:17
  • Actually after trying some things I have modified the question and asked at the end of the question, error: `Type id handling not implemented for type package.ClassName (by serializer of type package.CustomModule$CustomClassSerializer)` – BATMAN_2008 May 02 '22 at 16:24
  • 1
    I have posted my code sample here: https://stackoverflow.com/q/72089765/7584240 with this code I am getting the above mentioned error, can you please once have a look and provide some response? – BATMAN_2008 May 02 '22 at 17:58