1

I want to restructure an application so that it uses REST instead of an EJB3Factory which wasn't needed in the first place and only makes trouble with the new server.

Basically I have a class Request:

public class Request {
    public String name;
    public String id;
    public List<? extends someObject> list;

    // default constructor
    ...

    // non-default constructor
    public Request(String name, String id, List<T> list) {
        this.name = name;
        this.id = id;
        this.list = list;
    }

The Request gets created and using Gson made into a Json object:

Gson gson = new Gson();
String payload = gson.toJson(Request);

This then gets sent to the REST API on the server. There Jackson deserializes it. I do not have access to the Jackson implementation there and cannot change it to Gson.

What I am basically trying to do now is to get Jackson to use the non-default constructor to deserialize the object. I know I can annotate the non-default constructor like this:

@JsonCreator    
public Request(@JsonProperty("name") String name, @JsonProperty("id") 
        String id, @JsonProperty("list") List<T> list) {
    this.name = name;
    this.id = id;
    this.list = list;
}

The thing is though that the field name of list is set at runtime per reflection and the Gson object that is generated might have it as scenarioName1 for one and scenarioName2 for something else.

I have looked at the different solutions provided here on Stack Overflow but none of them could provide me with a solution for my problem. This seemed most helpful but I cannot under any circumstances use a wrapper property nor can I actually map all possibilities.

Anyone got any idea?

EDIT to include examples:

Example 1:

{"name":"someName","id":"first","someScenarioName":[{...}]}

Example 2:

{"name":"someOtherName","id":"second","differentScenarioName":[{...}]}

Since I'm out of town on business that is the best I can do with right now. It's basically the last field having a different name depending on which scenario was chosen beforehand.

EviL GaMer
  • 133
  • 13
  • Do you have any JSON return example? it would make it easier to understand. For example: example 1 -> {JSON content} example 2 -> {otherJSON content} – Eduardo Meneses Apr 23 '18 at 20:21

2 Answers2

1

Maybe you can try take a look on Mapper Features. Sincerely I didn't try it yet because I'm at work and so on, but I will send now my example and maybe it can help you:

public class Request {
   public String name;
   public String id;
   public List<? extends T> list;

   // default constructor
   ...

   // non-default constructor
   public Request(String name, String id, List<T> list) {
      this.name = name;
      this.id = id;
      this.list = list;
   }
}

Then to deserialize the object:

ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.USE_ANNOTATIONS, false);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.readValue(json, Request.class);

My try is because the deserialization by annotation is true by default, but once you don't have a "list" object most of time, it won't find the field there.

Eduardo Meneses
  • 504
  • 3
  • 18
  • Yes, I know about the different scenarios and the business logic etc. The thing is, there's like 40 or maybe 50 of them now. Your solution while valid is not applicable sadly. Every time a scenario gets included you already need to adjust 5 places in the code and I don't want to add to that as each code you need to change is prone to give more errors. I will look into the ObjectMapper, thanks – EviL GaMer Apr 24 '18 at 06:18
  • @KonradPuczynski but are the objects inside these dynamic lists the same? – Eduardo Meneses Apr 24 '18 at 13:48
  • @KonradPuczynski I edited my answer with some findings. Please take a look. – Eduardo Meneses Apr 24 '18 at 14:41
  • No, the objects inside the lists aren't the same either but I think that mapping should work out of the box because there are classes there to be mapped to and they all implement serializable. Thank you for your effort I will try some things on Friday when I'm back in the office. – EviL GaMer Apr 24 '18 at 18:15
  • @KonradPuczynski I just saw something similar (or at least that could help you) [here](http://www.baeldung.com/jackson-inheritance) – Eduardo Meneses Apr 24 '18 at 18:24
  • I did some tests. The ObjectMapper sadly doesn't help. I have tried to do `@JsonProperty("scenario1")` and it works. Sadly though that doesn't work then with following scenarios. I did try to use a string as a value but that doesn't seem to work either – EviL GaMer Apr 27 '18 at 12:03
0

Okay, so I figured out what my problem was. There are other lists in the class and those were the trouble. After annotating each of them with @JsonProperty("theirRespectiveName") it worked like a charm... Now I have to annotate about 100 lines of code and solve some more problems.

EviL GaMer
  • 133
  • 13