2

I'm trying to deserialize JSONs of specific structure into Java classes with Jackson. I have several classes like these:

class A {
  private int number1;
  private List<X> list1;
  private int number2;
}

class X {
  private String field1;
  private double value1;
}


class B {
  private String name2;
  private List<Y> list2;
}

class Y {
  private String field2;
}

And I get JSONs from external system like below:

{
  "number1": 1,
  "list1": {
    "elements": [{
      "field1": "Field 1 value 1",
      "value1": 2.2
    }, {
      "field1": "Field 1 value 2"
    }]
  },
  "number2": 2,
}


{
  "name2": "Name 2",
  "list2": {
    "elements": [{
      "field2": "Field 2 value 1"
    }]
  }
}

All I want is to write a custom deserializer, which could get rid of this elements level in a generic way (I mean to have one deserializer for all classes). Is there any simple way to extend a StdDeserializer to accomplish that or a I have to write a whole new deserializer with my custom algorithm?

Andrew Doe
  • 21
  • 2
  • do you have any idea how many alias names are there for `name1`? – Ryuzaki L Feb 03 '19 at 18:03
  • I don't get it, what does it change? It is just a technical issue. – Andrew Doe Feb 04 '19 at 01:32
  • we can do it in simple way other than custom deserializer – Ryuzaki L Feb 04 '19 at 01:40
  • 1
    In general these JSONs can have any structure and I updated example above. One thing is certain, that collections will be send like this: "collection_name": { "elements": [{ ... }] } and I'm trying to get rid of this **elements** level. – Andrew Doe Feb 04 '19 at 22:50
  • Related: https://stackoverflow.com/questions/11747370/jackson-how-to-process-deserialize-nested-json – shmosel Feb 05 '19 at 00:44
  • Thanks for link, but this do not help me in building generic solution, which allows to have lists on every level of JSON. – Andrew Doe Feb 13 '19 at 21:38

1 Answers1

0

You can take a look on this question: Jackson - deserialize inner list of objects to list of one higher level which is very similar. I have implemented there custom deserialiser which can be used for many different types with inner list. Your example POJO could look like this:

class A {
    private int number1;

    @JsonDeserialize(using = InnerListDeserializer.class)
    private List<X> list1;
    private int number2;

    // getters, setters
}

EDIT
If you do not want to use any annotation or custom deserialisation you need to create POJO structure which fit given JSON. You need to create middle POJO:

class ListWrapper<T> {

    private List<T> elements;

    // getter, setter, toString, etc
}

Now, you need to update classes A and B in this way:

class A {
    private int number1;
    private ListWrapper<X> list1;
    private int number2;

    // getters, setters, toString
}

and

class B {

    private String name2;
    private ListWrapper<Y> list2;

    // getters, setters, toString
}
Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
  • Sory for late answer. I want to solve this problem more generally and without Jackson annotations (I want to expose pure POJO classes without metadata). I can make an assumption that external system always serves collections like in JSON example (with elements level). – Andrew Doe Feb 13 '19 at 21:31
  • Quote from your question: "All I want is to write a custom deserializer, which could get rid of this elements level in a generic way". So, now, you do not want to implement custom deserialiser and create set of `POJO` classes which fit given `JSON`? – Michał Ziober Feb 13 '19 at 22:34
  • It is little misunderstanding. I want to register global deserializer in Jackson, to deserialize all lists (with elements level) in generic way, which means for me: without additional annotations on model. – Andrew Doe Feb 16 '19 at 23:54
  • I understand it now. This is a little bit tricky problem. As you can check, my custom deserialiser from other question uses `Jsckson` default deserialiser for a list. It is not an easy task to extend it properly and deserialise list by custom deserialiser. You need to know type of item and read all annotation used there. You can try to extend `com.fasterxml.jackson.databind.deser.std.CollectionDeserializer` but much easier is to use mine `InnerListDeserializer`. If you can not change classes use `MixIn` feature. If you think my answer does not help you I can delete it. – Michał Ziober Feb 17 '19 at 20:04