Creating JSON by combining fields from two classes - java

I have two classes : class A , class B
class A{
private int F1;
private String F2;
}
class B{
private int F3;
private String F4;
private String F5;
}
I want a JSON like this:
{
"F1": 123
"F2": "ABC"
"F3": 456
"F4": "CDE"
"F5": "FGH"
}
I am using springboot which creates JSON as soon as I return object from #RestController. How can I achieve the above json using these two classes.
Note :
1.) I already know that by using class A extends B , I can achieve
this but I am looking for some spring based method to achieve this
2.) Using #Embeddable in class B & then creating reference in Class A creates
additional tag B in JSON as shown :
{
"F1": 123
"F2": "ABC"
b: {
"F3": 456
"F4": "CDE"
"F5": "FGH"
}
}

How about using jackson #JsonUnwrapped?
http://fasterxml.github.io/jackson-annotations/javadoc/2.0.0/com/fasterxml/jackson/annotation/JsonUnwrapped.html
public class A{
#JsonUnwrapped
private B b;
public User getB() ...
}

Create a delegating class AB:
public final class AB {
private final A a;
private final B b;
public AB(A a, B b) {
this.a = a;
this.b = b;
}
// Delegation methods to A
public int getF1() { return this.a.getF1(); }
public String getF2() { return this.a.getF2(); }
// Delegation methods to B
public int getF3() { return this.b.getF3(); }
public String getF4() { return this.b.getF4(); }
public String getF5() { return this.b.getF5(); }
}

Related

Builder for existing classes

I have got the following scenario in which I got four classes autogenerated (in a JAR):
Class A{
B bEl = ...;
}
Class B{
C cEl = ...;
}
Class C{
D dEl = ...;
}
Class E{
E eEl=...;
}
Setting up those objects it is quite painful and error prone. Therefore, I was wondering if there is a better way to automatically construct a builder. I am aware of Lombok but I cannot edit that code and I cannot add the #Builder annotation.
Any recommendation?
If you are not allowed to change existing classes you can extend them:
public class Existing {
String a;
String b;
public Test(String a, String b) {
this.a = a;
this.b = b;
}
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
}
public class ExistingBuilder extends Existing {
#Builder
public ExistingBuilder(String a, String b) {
super(a, b);
// in case super class doesn't have all arguments constructor just call setters
// setA(a);
// setB(b);
}
}
So as you can see it's doable, but super class should have getters/setters or all args constructor.

How do I use method from super of super class

My program has 3 class. A, B, C. An instance variable is a private instance
class A {
private int a;
public int getX() {return a;}
public void setX(int a){this.a = a;}
}
class B extends A {
private int b;
public int getX() {return b;}
public void setX(int b){this.b = b;}
}
class C extends B {
private int c;
....
}
In class C I want to write a method that I must be used method getter and setter form class A and B
for getter and setter form class B I can write it but Class A I try to write this
class C extends B {
private in c;
public void method(){
A a = (A) this;
System.out.println(a.getX());
}
}
but the output is a value of class B, not A
how to do I can write it while No need to add method in class A, B, and C
My problem defines a private instance

Java 8 sort multiple objects

public class B {
private String name;
private String value;
//Setters and Get
}
public class C {
private String name;
private String value;
//Setters and Get Methods
}
public class D {
private String name;
private String value;
//Setters and Get
}
public class A {
private B b;
private C c;
private D d;
// Setters and Get
}
public class Example{
List<A> a = new Array List<A>();
//Lets assume a will contain objects of class B, C and D
a .sort( Comparator.comparing(A::getB().getName).thenComparing(A::getC().getName));
}
Sort field from one pojo , then sort field by next pojo.
Need to understand how to sort in this situation. Can we use
Comparator.comparing ()in this case?
You can't use method refences like that, but you could just use lambda expressions:
a.sort(Comparator.comparing((A x) -> x.getB().getName())
.thenComparing(x -> x.getC().getName()));

Java Builder Pattern - deep object copy

I have a Jaxb object that has an object tree 3 deep. I have created a seperate object that mirrors this Jaxb object. I am using the builder pattern to copy values from Jaxb to the bean. The issue is, when building A, I require an instance of B. But, the verion of B that the builder requires is different from the Jaxb version of B -the 'source'.
How do I build A?
public class A {
private B b;
public void setB(B b) {
this.b = b;
}
public static class ABuilder {
private B b;
public ABuilder withB(B b) {
this.b = b;
return this;
}
A build() {
A a = new A();
a.setB(b);
return a;
}
}
}
class B {
private C c;
private String name;
}
class C {
private int count;
}
class myMain {
com.myJaxb.B jaxbB;
A myA = new A.ABuilder().withB(jaxbB).build(); //error - withB doesnt take jaxb B
}

Minimize JSON to deserialize and persist complex POJO with JPA/Hibernate

I have a fairly complex POJO that I need to deserialize from a JSON string and persist in a MySQL database. The following is a very simplified example class:
#Entity
#Table(name="a")
public class A{
private Long id;
private B b;
private C c;
private D d;
}
#ManyToOne
#JoinColumn(name="b_id")
public B getB(){
return this.b;
}
public void setB(B b){ this.b = b; }
#ManyToOne
#JoinColumn(name="c_id")
public C getC(){
return this.c;
}
public void setC(C c){ this.c = c; }
#ManyToOne
#JoinColumn(name="d_id")
public D getD(){
return this.d;
}
public void setD(D d){ this.d = d; }
Each class B, C, and D also have a number of fields and objects (some with even more required objects and fields) that can not be null according to the database schema, which I can't change. I can deserialize and persist this no problem, but the JSON required to do so is really massive. I only need to persist the deserialized A, so I really just need the _id fields from B, C, and D.
Right now my JSON is something like:
{
"id":1,
"b":{"id":2, ...},
"c":{"id":3, ...},
"d":{"id":4, ...}
}
where I have to fill in all the non-nullable database fields. What I would like to do is read a JSON string like:
{
"id":1,
"b_id":2,
"c_id":3,
"d_id":4
}
and just have Hibernate/JPA update those fields in the database. I think the real tricky part is that other classes/methods in my application will need the entire object hierarchy for reading from the database. The only time I can use just the _id fields is during the deserialization of the JSON. When this is the case, I only need to update the top-most object (A in my example) and some other trivial fields. In a perfect world, I can just throw some annotations on my class to solve this problem, but I haven't found anything capable of doing this.
Is this even possible? If so, can it be done with JPA/Jackson annotations?
Thanks!
If mapping the JSON directly to your entities is akward, I would simply make the translation from the incoming JSON string to your entities explicit via an intermediate object (call it a DTO if you will).
I also have a gut feeling that if you save associated object references (the #ManyToOnes) with only the id populated, Hibernate will in fact save the association correctly (root object here represents A):
{
"id" : 1,
"b" : {
"id" : 2
},
...
}
Make sure you don't cascade the persist operation for the b, c etc. fields.
You should create new classes which define only this fields which you want to deserialize. For example if you want to deserialize only ID your class could looks like this:
class JsonEntity {
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#JsonAnySetter
public void setUnknownProperties(String name, String value) {
//do nothing
}
#Override
public String toString() {
return String.valueOf(id);
}
}
In this example annotation JsonAnySetter do the trick. Now, you have to create some class which will be simulating your A class. For example:
class DtoA extends JsonEntity {
private JsonEntity b;
private JsonEntity c;
private JsonEntity d;
public JsonEntity getB() {
return b;
}
public void setB(JsonEntity b) {
this.b = b;
}
public JsonEntity getC() {
return c;
}
public void setC(JsonEntity c) {
this.c = c;
}
public JsonEntity getD() {
return d;
}
public void setD(JsonEntity d) {
this.d = d;
}
#Override
public String toString() {
return "A [id=" + getId() + ", b=" + b + ", c=" + c + ", d=" + d + "]";
}
}
Now when we have new JSON data model we can test it. For example we can parse below JSON:
{
"id":1,
"b":{"id":2, "p1":"v1", "p2":"v2"},
"c":{"id":3, "p3":"v3", "p4":"v4", "p5":"v5"},
"d":{"id":4, "p6":"v6"}
}
Deserialization example:
ObjectMapper objectMapper = new ObjectMapper();
DtoA a = objectMapper.readValue(json, DtoA.class);
System.out.println(a);
Above program prints:
A [id=1, b=2, c=3, d=4]
Now, you have to implement toA() method in DtoA class which could look like this:
public A toA() {
A a = new A(getId());
a.setB(new B(getB().getId()));
a.setC(new C(getC().getId()));
a.setD(new D(getD().getId()));
return a;
}
Let me know whether it works for you.

Categories