0

the goal is to force the override of the getter which returns a constant when I serialize. I search a solution on classes side, not on the serializer.

import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import com.google.gson.Gson;

    abstract class AbstractClass implements Serializable {
        @Setter
        @Getter
        private String abstractVariable;

        public abstract String getAbstractVariable();
    }

    @Data
    class ConcreteClass extends AbstractClass implements Serializable {
        private String concreteVariable;

        @Override
        public String getAbstractVariable() {
            return "Constant Value";
        }
    }

Gson gson = new Gson();
System.out.println("ConcreteClass="+gson.toJson(new ConcreteClass()));
=>
ConcreteClass={}

This solution doesn't work, I tried many things without success: @Getter(AccessLevel.NONE) @Expose(serialize = false) ...

Larvis
  • 3
  • 3
  • 1
    Why not simply assign your constant value to the `abstractVariable` in the parent class? – Jorn Jun 23 '23 at 08:48
  • Also, doesn't the duplicate declaration of `public abstract String getAbstractVariable();` together with the `@Getter` cause a problem? I'm not sure which one wins. – Jorn Jun 23 '23 at 08:50
  • @Jorn because each class extending AbstractClass needs to set its own value. And same bad result without Getter – Larvis Jun 23 '23 at 09:08
  • Gson doesn't use getters but access fields directly. Use Jackson instead. It uses getters/setters and has plenty annotations for configuration. – Mar-Z Jun 23 '23 at 09:08
  • @Mar-Z Thanks, but the serializer is a service that I mustn't touch, I'm looking for a solution with Gson – Larvis Jun 23 '23 at 09:17
  • In this case you will need to modify the field. As I said: Gson doesn't use getters but access fields directly. – Mar-Z Jun 23 '23 at 09:22

1 Answers1

0

As GSON uses reflection to access fields and not getters/setters my solution can't work. I tried to use Gson JsonSerializer and TypeAdapter but their methods can't access to the field's parent instance to call the getter (too bad it would be cool and would offer lots of possibilities).

So to force the set of abstractVariable I now use a constructor in the abstract class. Because of this I cannot use anymore @Data in the extended class and have to replace it by many annotations :

@Data
abstract class AbstractClass implements Serializable {

    public AbstractClass(String abstractVariable) {
        this.abstractVariable = abstractVariable;
    }

    private String abstractVariable;
}

@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Getter
@Setter
class ConcreteClass extends AbstractClass {
    public ConcreteClass() {
        super("const");
    }

    private String concreteVariable;
}

Gson gson = new Gson();
System.out.println("ConcreteClass="+gson.toJson(new ConcreteClass()));
=>
ConcreteClass={"abstractVariable":"const"}

If anyone sees another solution I'm curious to know it especially if it's simpler

Larvis
  • 3
  • 3