#JsonInclude(JsonInclude.Include.NON_DEFAULT)
I have a nested class structure as follows:
public class A{
String z;
String y;
float p;
List<B> b;
public static class B{
String x;
String w;
float q;
List<C> c;
public static class C{
String v;
String u;
float r;
}
}
}
I have another class as follows:
public class D{
List<B> b;
}
In my use case, I am returning class D as part of an API call. String x(in class B) and String v(in class C) will always be non-null. But String w and String u may or may not be null. I want to exclude null fields and default fields ( like 0.0 for float q and float r) from my response and therefore want to use #JsonInclude(JsonInclude.Include.NON_DEFAULT). But I don't want this to happen for all use cases, but only for my use case, i.e. only for class D? Is the following an effective way of achieving it?
#JsonInclude(JsonInclude.Include.NON_DEFAULT)
public class D{
List<B> b;
}
Will the above way work on the inner classes as well? Please feel free to suggest another method because I'm unable to think of one.
Related
I have a class
#Value
#NonFinal
public class A {
int x;
int y;
}
I have another class B
#Value
public class B extends A {
int z;
}
lombok is throwing error saying it cant find A() constructor, explicitly call it what i want lombok to do is to give annotation to class b such that it generates the following code:
public class B extends A {
int z;
public B( int x, int y, int z) {
super( x , y );
this.z = z;
}
}
Do we have an annotation to do that in Lombok?
This is not possible in Lombok. Although it would be a really nice feature, it requires resolution to find the constructors of the super class. The super class is only known by name the moment Lombok gets invoked. Using the import statements and the classpath to find the actual class is not trivial. And during compilation you cannot just use reflection to get a list of constructors.
It is not entirely impossible but the results using resolution in val and #ExtensionMethod have taught us that is it hard and error-prone.
Disclosure: I am a Lombok developer.
Lombok Issue #78 references this page https://www.donneo.de/2015/09/16/lomboks-builder-annotation-and-inheritance/ with this lovely explanation:
#AllArgsConstructor
public class Parent {
private String a;
}
public class Child extends Parent {
private String b;
#Builder
public Child(String a, String b){
super(a);
this.b = b;
}
}
As a result you can then use the generated builder like this:
Child.builder().a("testA").b("testB").build();
The official documentation explains this, but it doesn’t explicitly point out that you can facilitate it in this way.
I also found this works nicely with Spring Data JPA.
Version 1.18 of Lombok introduced the #SuperBuilder annotation. We can use this to solve our problem in a simpler way.
You can refer to https://www.baeldung.com/lombok-builder-inheritance#lombok-builder-and-inheritance-3.
so in your child class, you will need these annotations:
#Data
#SuperBuilder
#NoArgsConstructor
#EqualsAndHashCode(callSuper = true)
in your parent class:
#Data
#SuperBuilder
#NoArgsConstructor
Lombok does not support that also indicated by making any #Value annotated class final (as you know by using #NonFinal).
The only workaround I found is to declare all members final yourself and use the #Data annotation instead. Those subclasses need to be annotated by #EqualsAndHashCode and need an explicit all args constructor as Lombok doesn't know how to create one using the all args one of the super class:
#Data
public class A {
private final int x;
private final int y;
}
#Data
#EqualsAndHashCode(callSuper = true)
public class B extends A {
private final int z;
public B(int x, int y, int z) {
super(x, y);
this.z = z;
}
}
Especially the constructors of the subclasses make the solution a little untidy for superclasses with many members, sorry.
for superclasses with many members I would suggest you to use #Delegate
#Data
public class A {
#Delegate public class AInner{
private final int x;
private final int y;
}
}
#Data
#EqualsAndHashCode(callSuper = true)
public class B extends A {
private final int z;
public B(A.AInner a, int z) {
super(a);
this.z = z;
}
}
If child class has more members, than parent, it could be done not very clean, but short way:
#Data
#RequiredArgsConstructor
#EqualsAndHashCode(callSuper = true)
#ToString(callSuper = true)
public class User extends BaseEntity {
private #NonNull String fullName;
private #NonNull String email;
...
public User(Integer id, String fullName, String email, ....) {
this(fullName, email, ....);
this.id = id;
}
}
#Data
#AllArgsConstructor
abstract public class BaseEntity {
protected Integer id;
public boolean isNew() {
return id == null;
}
}
As a workaround while there is no proper annotation, you could use com.fasterxml.jackson.databind.ObjectMapper to initialize a child class from the parent
public class A {
int x;
int y;
}
public class B extends A {
int z;
}
ObjectMapper MAPPER = new ObjectMapper(); //it's configurable
MAPPER.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false );
MAPPER.configure( SerializationFeature.FAIL_ON_EMPTY_BEANS, false );
//Then wherever you need to initialize child from parent:
A parent = new A(x, y);
B child = MAPPER.convertValue( parent, B.class);
child.setZ(z);
You can still use any lombok annotations on A and B if you need.
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
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(); }
}
I've encountered situation when I need two classes have same fields, but a slightly different behavior, one of them possess some other field, but another doesn't, so the questions is : do i have to map derived class which have no special fields?
Here's example, let's say i have class A, and class B, both have to have some collection(e.g. of C objects) and some other field D, so i create abstract class AB, which is their parent, and while class B also have String field, class A - doesn't, and all of them are descendants of M, which have someMethod():
abstract class M {
//fields, getters, etc
public void someMethod(){
//doSmth
}
}
abstract class AB extends M {
private D d;
private Set<C> cs;
//getters, setters, etc
}
class A extends AB{
#Override
public void someMethod(){
for(C c : cs){
//doSmth
}
}
}
class B extends AB {
private String text;
//getters etc
}
So, I definitely should map M, AB and B, but should i map A?
P.S. we use xml mappings
If you want Hibernate to return you List<A> as a query result, yes you'd need to map A.
I have a super class named Transformer. and I have two derived classes that converts class A to B and vice versa. There is the classes :
class A{
private Long id;
private String name;
... getter and setters
}
class B{
private Long id;
private String name;
... getter and setters
}
interface Transformer<S,D> {
D convert(S source);
}
class ATransformer implements Transformer<A,B>{
public B convert(A a){
B b=new B();
b.setId(a.getId());
.....
return b;
}
}
class BTransformer implements Transformer<B,A>{
public A convert(B b){
A a=new A();
a.setId(b.getId());
.....
return a;
}
}
as you see, derived transformer classes have duplicate codes. Is there any design or solution to avoid this duplication without using reflection?
You can use a bean mapper framework like Dozer or orika to do the work for you (and spare you the duplicate code).
However as already mentioned in the other comments, it is (in most cases) preferable to avoid having classes that are nearly the same without them being in the same class hirarchy and therefore castable.