convert class to another class with json(Jackson framework)
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 + "]";
}
}
OranGE
Updated on June 04, 2022Comments
-
OranGE almost 2 years
Two classes have similar fields, but they don't have superclass. In my code :
First
andSecond
classes. I need to write methodconvertToAnother
, what will be return object of classresultClassObject
with values of fields from objectone
. Both classes have Json annotation. That annotation have vaule of property equals name of class in lowercase (in my code classFirst
haveclassName = "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 about 7 yearsYour question about assuming that the field name is
className
is valid, but poorly put. To improve the quality of your answer I suggest still usingclassName
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 about 7 yearsI 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 over 4 yearsWelcome 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 over 4 yearsI changed my answer
-
wonsuc about 2 yearsDozer is discontinued now.
-
wonsuc about 2 yearsDozer is discontinued now.