FasterXML / jackson-modules-java8

Set of support modules for Java 8 datatypes (Optionals, date/time) and features (parameter names)
Apache License 2.0
399 stars 116 forks source link

Optional object Serialization Whole Object required instead of value. #261

Closed prakharporwal closed 1 year ago

prakharporwal commented 1 year ago

What I want

{
    "present": true,
     "value": {
            "id": 8
      }
}

What I get right now

{
   "id":  8
}
cowtowncoder commented 1 year ago

@prakharporwal There is no way to serialize Optional "as POJO" right now; in theory @JsonFormat(shape = JsonFormat.Shape.OBJECT) might work , and that would provide present but since "value" is accessed with get() (and not getValue()) that would not be serialized even then. It'd have to be applied either via "config overrides" system (for global setting) or annotation on Optional<x> valued property.

... theoretically, of course, mix-in annotation could be added on get(), but I don't know if combination actually would work (depends on individual serializer implementation).

More likely though you can make this work with custom serializer. One challenge there may be is handling of generic types -- if you need to find value type, cannot use SimpleModules addSerializer() methods, but need to implement Serializers provider. But it is possible you don't need to worry about that if the default serializer for value types you use work fine (are non-generic types).

prakharporwal commented 1 year ago

@cowtowncoder Thanks for responding. If I am not able to serialise Optional completely into a POJO. Can you help me the below case ?

How do I deserialise the Value part of Optional which is recorded into an Optional value.

The Object is a nested-generic type and I want to convert the JSON to Optional. I am using the JDK8 module (2.13.4) already with jackson (2.13) and I am not sure why it is failing.

Here is Example of my case :

Currently I am using this : [ Updated ]

 private final static ObjectMapper objectMapper = new ObjectMapper();
      objectMapper.register(new Jdk8Module());

      objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
      objectMapper.configure(SerializationFeature.FAIL_ON_SELF_REFERENCES, false);
      objectMapper.configure(SerializationFeature.WRITE_SELF_REFERENCES_AS_NULL, true);

      objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
      objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true)

       String stringSource = // reads the bottom json file and returns a JSON String;
      JsonNode JSON =   objectMapper.readValue(stringSource, JsonNode.class);

      Optional<List<List<String>>> val = mapper.readValue( JSON.get("object").toString(),
                       new TypeReference<Optional<List<List<String>>>(){}.getType() );

Json File Which I read from -

{
  "object": [
    [ "first","second"],
    ["third","fourth"],
  ]
}

I expect the val to have the value properly deserialized. Am I doing something wrong here ?

I get this error

java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.MismatchedInputException: 
Cannot deserialize value of type `java.util.Optional>>` 
from Array value (token `JsonToken.START_ARRAY`)
cowtowncoder commented 1 year ago

What does JSON["object"] here refer to? What is the actual JSON content being read?

Also: you are not registering module for Optional support in your example so that would prevent it from working.

prakharporwal commented 1 year ago

@cowtowncoder

Registering the Jdk8Module works for me. I missed that part. Thank you!

cowtowncoder commented 1 year ago

You are welcome @prakharporwal !