4

I'm using Jackson to deserialise a class which has Optional member variables, so it looks like

class Test{
   Optional<String> testString;
}

but in serialised form it looks like, which is legit

{
"value": {
"testString": "hi"
}

How can I deserialise it back to my Test class?, because when I try to do so it says unknown field "value". Can it be possible without changing my test class.

Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
  • 1
    Possibly related [link](https://stackoverflow.com/questions/24547673) and to understand better why `Optional` as a field type should not be preferred. – Naman Feb 15 '19 at 06:28
  • @nullpointer, its valid but the class which iam using is from third party lib – Siddharth Thakrey Feb 15 '19 at 06:37

1 Answers1

2

You need to register Jdk8Module. Belowe you can find example, how to do that:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;

import java.io.File;
import java.util.Optional;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new Jdk8Module());

        Test test = new Test();
        test.setTestString(Optional.of("str"));

        String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(test);
        System.out.println(json);
        System.out.println(mapper.readValue(json, Test.class));
    }
}

Above code prints:

{
  "testString" : "str"
}
Test{testString=Optional[str]}

See also:

  1. jackson-modules-java8
Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
  • in your case you are creating a new object but in my case i am try to deserialize the json { "value": { "testString": "hi" }, which is being read from file. – Siddharth Thakrey Feb 18 '19 at 05:53
  • When you will enable `Jdk8Module` and serialise your `Test` object it will be look like in my example. So, deserialisation will start working without any changes. If you want to keep old version of `JSON` with `value` in root object you need to update `POJO`s structure. Can you change `JSON`? If yes, regenerate it with `Jdk8Module`. If no, you need to change `POJO` structure. Which version of `Jackson` do you use? Do you use `FasterXML` or `codehaus`? – Michał Ziober Feb 18 '19 at 08:19
  • @SiddharthThakrey, have you fixed your problem? – Michał Ziober Mar 11 '19 at 19:26
  • in my case the api is serializing response without using Jdk8Module which looks like { "present": true "value"{ "testString": "abc" }} and iam trying to deserialize this above form of TestClass which looks like , cause that's third party api response – Siddharth Thakrey Mar 15 '19 at 04:37
  • @SiddharthThakrey, when I try to serialise `private Optional testString = Optional.of("Test")` the result is: `{"testString":{"present":true}}` Do you use any custom serialiser? That's strange that `testString` is inside `value` in your case. It should be something like: `{"testString": {"present": true,"value": "abc"}}`. In your case it is not possible to match `JSON` property with `Test`'s class `testString` property. – Michał Ziober Mar 15 '19 at 07:36
  • you are correct. yeah i mean i am getting in {"testString": {"present": true,"value": "abc"}} as the serialised form, my bad but still it is failing in deserialisation . – Siddharth Thakrey Jul 10 '19 at 08:22
  • @SiddharthThakrey, in that case you need to implement custom deserializer. – Michał Ziober Jul 10 '19 at 08:36