Jackson Databind ObjectMapper convertValue with custom mapping implementaion
Asked Answered
T

2

8

Foo1

public class Foo1{

private Long id;
private String code;
private String name;
private Boolean rState;
private String comments;     // Contain json data
private String attachments;  // Contain json data

}

Foo2

public class Foo2{

private Long id;
private String code;
private String name;
private Boolean rState;
private List comments;
private List attachments;

}

convert value

new ObjectMapper().convertValue(foo1, Foo2.class);

is it possible, when I call convert value, json String automatically convert to list ?

Torrietorrin answered 8/12, 2019 at 5:26 Comment(0)
T
1

I would recommend going with a Deserializer as Foo1 might actually be serialized elsewhere and we might only have it's serialized data to convert. And that is what is our goal here.

Create a SimpleModule that deserializes List type

public class ListDeserializer extends StdDeserializer<List> {

    public ListDeserializer() {
        super(List.class);
    }

    @Override
    public List deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException {
        if (p.getCurrentName().equals("result") || p.getCurrentName().equals("attachments")) {
            JsonNode node = p.getCodec().readTree(p);
            return new ObjectMapper().readValue(node.asText(), List.class);
        }
        return null;
    }
}

The above deserializer only recognizes result and attachments and ignores the rest. So this is a very specific deserializer for List in Foo2 class.

My test Foo1 and Foo2 are as follows

public class Foo1 {

    String result = "[\"abcd\", \"xyz\"]";

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }
}

public class Foo2 {

    List result;

    public List getResult() {
        return result;
    }

    public void setResult(List result) {
        this.result = result;
    }
}

I tested the above code as follows

// Module to help deserialize List objects
SimpleModule listModule = new SimpleModule();
listModule.addDeserializer(List.class, new ListDeserializer());

ObjectMapper objectMapper = new ObjectMapper().registerModules(listModule);
Foo2 foo2 = objectMapper.convertValue(new Foo1(), Foo2.class);
System.out.println(foo2.getResult());

And the output is

[abcd, xyz]
Tautog answered 8/12, 2019 at 11:25 Comment(0)
H
0

Option 1 : Just annotate the getter method of the Foo1.class

@JsonProperty("comments")
        public List getComments() {
            List list = new ArrayList();
            list.add(comments);
            return list;
        }

 @JsonProperty("attachments")
        public List getAttachments() {
            List list = new ArrayList();
            list.add(attachments);
            return list;
        }


Foo1 foo1 = new Foo1(Long.valueOf(1),"a","aaa",true,"abc","def");
System.out.println(new ObjectMapper().writeValueAsString(foo1));
Foo2 foo2 = new ObjectMapper().convertValue(foo1, Foo2.class);
System.out.println(new ObjectMapper().writeValueAsString(foo2));

Option 2 : use jackson-custom-serialization

ObjectMapper mapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Foo1.class,new ListSerializer());
mapper.registerModule(simpleModule);


public class ListSerializer extends StdSerializer<Foo1> {

    public ListSerializer() {
        this(null);
    }

    protected ListSerializer(Class<Blah.Foo1> t) {
        super(t);
    }

    public void serialize(Blah.Foo1 foo1, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeStartObject();
        List list = new ArrayList();
        list.add(foo1.getComments());

        List list1 = new ArrayList();
        list1.add(foo1.getAttachments());

        jsonGenerator.writeObjectField("id",foo1.getId());
        jsonGenerator.writeObjectField("code",foo1.getCode());
        jsonGenerator.writeObjectField("name",foo1.getName());
        jsonGenerator.writeObjectField("rState",foo1.getrState());
        jsonGenerator.writeObjectField("comments",list);
        jsonGenerator.writeObjectField("attachments",list1);
        jsonGenerator.writeEndObject();
    }
}


Foo1 foo1 = new Foo1(Long.valueOf(1),"a","aaa",true,"abc","def");
System.out.println(mapper.writeValueAsString(foo1));
Foo2 foo2 = mapper.convertValue(foo1, Foo2.class);
System.out.println(new ObjectMapper().writeValueAsString(foo2));
Highjack answered 8/12, 2019 at 7:22 Comment(1)
I don't want to create getter method as I am using lombok.Torrietorrin

© 2022 - 2024 — McMap. All rights reserved.