2

I have created a Jackson Custom Deserializer to deserialize a JSON string :

public class TestMapper extends StdDeserializer<Test> {

    public TestMapper() {
        this(null);
    }

    public TestMapper(Class<?> vc) {
        super(vc);
    }

    @Override
    public Test deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {

I want to pass a "String argument" to the deserialize method that I want to use during deserialization. Is there a way to do that?

I'm calling the deserializer as follows in my code:

new ObjectMapper().readValue(json, Test.class)

and the Test Class is :

@JsonDeserialize(using = TestMapper.class)
public class Test {
apandey
  • 85
  • 1
  • 4
  • 13
  • you can pass any argument in the constructor – Sharon Ben Asher Mar 06 '19 at 17:07
  • @SharonBenAsher -- I'm calling the desealizer as follow - new ObjectMapper().readValue(json, Test.class) and the Test Class has the @JsonDeserialize(using = TestMapper.class) annotataion. How can I pass the value in new ObjectMapper().readValue(json, Test.class) using constructor ? – apandey Mar 06 '19 at 17:17
  • you can register a deserializer programatically. see answer to this https://stackoverflow.com/questions/6553051/setting-up-json-custom-deserializer – Sharon Ben Asher Mar 06 '19 at 17:39
  • If I add the constructor public TestMapper(String test) { }, I get the message there is no default constructor available for the superclass. – apandey Mar 06 '19 at 18:39
  • @SharonBenAsher, adding public TestMapper(String test) {super(Test.class);this. test = test;} worked. Thanks for the help! – apandey Mar 06 '19 at 19:38

1 Answers1

4

You need to create constructor which takes your extra argument which will be used during deserialisation:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;

import java.io.IOException;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        SimpleModule customModule = new SimpleModule();
        customModule.addDeserializer(Test.class, new TestMapper("Extra value!!!"));

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(customModule);

        Test test = new Test();
        test.setValue("Value");

        String json = mapper.writeValueAsString(test);
        System.out.println(json);
        System.out.println(mapper.readValue(json, Test.class));
    }
}

class TestMapper extends StdDeserializer<Test> {

    private String extraConfig;

    public TestMapper() {
        this(null);
    }

    public TestMapper(String extraConfig) {
        super(Test.class);
        this.extraConfig = extraConfig;
    }

    @Override
    public Test deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        Test test = new Test();
        test.setValue(extraConfig);

        return test;
    }
}

class Test {

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Test{" +
                "value='" + value + '\'' +
                '}';
    }
}

Above code prints:

{"value":"Value"}
Test{value='Extra value!!!'}

You should always provide to super constructor your POJO class, for example, Test.class. If you need more complex initialisation, take a look on ContextualDeserializer.

Also, take a look:

Michał Ziober
  • 37,175
  • 18
  • 99
  • 146