convert class to another class with json(Jackson framework)

14,679

Solution 1

The only correct way to do that using jackson is to marshall instance to json and then unmarshall. I would recommend to use convertion on the level of java objects - using Dozer: http://dozer.sourceforge.net

Solution 2

I want to offer such a solution, example for class First:

First first = new First();
first.i = 1;
first.name = "first";
Second s = (Second) convertOneToAnother(first, Second.class);
System.out.println(s.name); // first

ObjectMapper mapper = new ObjectMapper();

// here we disable uses annototions, since by the condition of the 
// problem, we have two classes have similar fields
mapper.disable(MapperFeature.USE_ANNOTATIONS);

StringWriter writer = new StringWriter();
mapper.writeValue(writer, one);
//writer.toString() == {"i":1,"name":"first"}

mapper.readValue(writer.toString, resultClassObject);

if we don't use method mapper.disable(), we'll have for writer, such string {"className":"first","i":1,"name":"first"}

Solution 3

You can write code like below for model mapping:

public class ModelConverter {

public static void main(String[] args) throws IOException {
    Test1 t1 = new Test1();
    ObjectMapper mapper1 = new ObjectMapper();
    String jsonString = mapper1.writeValueAsString(t1);
    System.out.println(jsonString);
    Test2 t2 = mapper1.readValue(jsonString, Test2.class);
    System.out.println(t2);
}
}
public class Test1 implements Serializable {
private int i = 10;
private String name = "demo1";
private Test3 test3 = new Test3();

public int getI() {
    return i;
}

public void setI(int i) {
    this.i = i;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Test3 getTest3() {
    return test3;
}

public void setTest3(Test3 test3) {
    this.test3 = test3;
}

@Override
public String toString() {
    return "test1 [i=" + i + ", name=" + name + ", Test3=" + test3 + "]";
}
}
public class Test2 implements Serializable {
private int i = 11;
private String name = "demo2";
private Test3 test3;

public int getI() {
    return i;
}

public void setI(int i) {
    this.i = i;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Test3 getTest3() {
    return test3;
}

public void setTest3(Test3 test3) {
    this.test3 = test3;
}

@Override
public String toString() {
    return "test2 [i=" + i + ", name=" + name + ", Test3=" + test3 + "]";
}
}

public class Test3 implements Serializable {
private int i = 12;
private String name = "demo3";

public int getI() {
    return i;
}

public void setI(int i) {
    this.i = i;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

@Override
public String toString() {
    return "test3 [i=" + i + ", name=" + name + "]";
}
}
Share:
14,679
OranGE
Author by

OranGE

Updated on June 04, 2022

Comments

  • OranGE
    OranGE almost 2 years

    Two classes have similar fields, but they don't have superclass. In my code : First and Second classes. I need to write method convertToAnother, what will be return object of class resultClassObject with values of fields from object one. Both classes have Json annotation. That annotation have vaule of property equals name of class in lowercase (in my code class First have className = "first".

    import com.fasterxml.jackson.annotation.JsonSubTypes;
    import com.fasterxml.jackson.annotation.JsonTypeInfo;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    import java.io.IOException;
    import java.io.StringReader
    
    public class Solution {
        public static void main(String[] args) throws IOException {
            Second s = (Second) convertOneToAnother(new First(), Second.class);
            First f = (First) convertOneToAnother(new Second(), First.class);
        }
    
        public static Object convertOneToAnother(Object one, Class resultClassObject) throws IOException {
            try {
                ObjectMapper mapper = new ObjectMapper();
                String obj = mapper.writeValueAsString(one);
                obj = obj.replace("\"className\":\"" + one.getClass().getSimpleName().toLowerCase() + "\"", "\"className\":\"" + resultClassObject.getSimpleName().toLowerCase() + "\"");
                return new ObjectMapper().readValue(new StringReader(obj), resultClassObject);
            }
            catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
    
        }
    
        @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,  property="className")
        @JsonSubTypes(@JsonSubTypes.Type(value=First.class,  name="first"))
        public static class First {
            public int i;
            public String name;
        }
    
        @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,  property="className")
        @JsonSubTypes(@JsonSubTypes.Type(value=Second.class, name="second"))
        public static class Second {
            public int i;
            public String name;
        }
    }
    

    Maybe another decision exist?

  • toonice
    toonice about 7 years
    Your question about assuming that the field name is className is valid, but poorly put. To improve the quality of your answer I suggest still using className in your second code segment and changing the contents of your bracketed comment to (in your code you assume that the field name is "className", but you can call it just about anything else if you wish).
  • Admin
    Admin about 7 years
    I don't want to say that you can call it how you wish. It didn't mention in the question that field name is "className". "That annotation have value of property equals name of class in lowercase" - that is it, so the name field is not fixed or controlled by conversion function
  • B--rian
    B--rian over 4 years
    Welcome to SO, we appreciate your input! Could you please edit your answer and explain a bit what you are doing and why? For more guidance see stackoverflow.com/help/how-to-answer
  • space
    space over 4 years
    I changed my answer
  • wonsuc
    wonsuc about 2 years
    Dozer is discontinued now.
  • wonsuc
    wonsuc about 2 years
    Dozer is discontinued now.