1

I'm creating a common class to standardize my JSON structure as written below,

public class Wrapper<T> {
   private SoaHeader soaHeader;
   private T payload;
}

public class PayloadFoo {
   private String foo;
}

public class PayloadBar {
   private String bar;
}

public class main(){
   var foo = new Wrapper<PayloadFoo>();
   var bar = new Wrapper<PayloadBar>();
}

Then later the expected JSON result for both foo and bar are

{
   "foo": {
      "soaHeader": {},
      "payload": {
         "foo": ""
      }
   }
}

and

{
   "bar": {
      "soaHeader": {},
      "payload": {
         "bar": ""
      }
   }
}

Can Jackson do such task by put either @JsonTypeName or @JsonRootName annotation on the PayloadFoo and PayloadBar classes? or any suggestion how can I achieve this? Thankyou

Varid Vaya
  • 194
  • 1
  • 15
  • No you can't because of [type erasure on generic types](https://stackoverflow.com/questions/6846244/jackson-and-generic-type-reference/6852184#6852184). – John Williams Jan 28 '23 at 12:09

1 Answers1

0

Jackson can handle this by using the @JsonTypeName annotation on the PayloadFoo and PayloadBar classes and the @JsonTypeInfo annotation on the Wrapper class.

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

public class JsonSubTypesExample {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
            .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

    public static void main(String[] args) throws JsonProcessingException {

        Wrapper<PayloadFoo> payloadFooWrapper = new Wrapper<>(new SoaHeader(), new PayloadFoo("foo"));
        Wrapper<PayloadBar> payloadBarWrapper = new Wrapper<>(new SoaHeader(), new PayloadBar("bar"));

        System.out.println(OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(payloadFooWrapper));
        System.out.println(OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(payloadBarWrapper));
    }
    
    @JsonSubTypes({
            @JsonSubTypes.Type(value = PayloadFoo.class, name = "foo"),
            @JsonSubTypes.Type(value = PayloadBar.class, name = "bar"),
    })
    @Data
    @ToString
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Wrapper<T> {
        private SoaHeader soaHeader;
        private T payload;
    }

    @JsonTypeName("foo")
    @Data
    @ToString
    @NoArgsConstructor
    @AllArgsConstructor
    public static class PayloadFoo {
        private String foo;
    }

    @JsonTypeName("bar")
    @Data
    @ToString
    @NoArgsConstructor
    @AllArgsConstructor
    public static class PayloadBar {
        private String bar;
    }

    @Data
    @ToString
    public static class SoaHeader {

    }
}