3

Is it possible to use Jersey with Moxy to/from Json and Java 8 Optionals?

How to configure it?

kalamar
  • 933
  • 1
  • 11
  • 27

1 Answers1

0

You can declare following class:

public class OptionalAdapter<T> extends XmlAdapter<T, Optional<T>> {

    @Override
    public Optional<T> unmarshal(T value) throws Exception {
        return Optional.ofNullable(value);
    }

    @Override
    public T marshal(Optional<T> value) throws Exception {
        return value.orElse(null);
    }

}

And use like this:

@XmlRootElement
public class SampleRequest {

    @XmlElement(type = Integer.class)
    @XmlJavaTypeAdapter(value = OptionalAdapter.class)
    private Optional<Integer> id;

    @XmlElement(type = String.class)
    @XmlJavaTypeAdapter(value = OptionalAdapter.class)
    private Optional<String> text;

    /* ... */

}

Or declare in package-info.java and remove @XmlJavaTypeAdapter from POJOs:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapters({
        @XmlJavaTypeAdapter(type = Optional.class, value = OptionalAdapter.class)
})

But here are some drawbacks:

  1. Adapter above can only work with simple types like Integer, String, etc. that can be parsed by MOXY by default.
  2. You have to specify @XmlElement(type = Integer.class) explicitly to tell the parser type are working with, otherwise null values would be passed to adapter's unmarshal method.
  3. You miss the opportunity of using adapters for custom types, e.g. custom adapter for java.util.Date class based on some date format string. To overcome this you'll need to create adapter something like class OptionalDateAdapter<String> extends XmlAdapter<String, Optional<Date>>.

Also using Optional on field is not recommended, see this discussion for details.

Taking into account all the above, I would suggest just using Optional as return type for your POJOs:

@XmlRootElement
public class SampleRequest {

    @XmlElement
    private Integer id;

    public Optional<Integer> getId() {
        return Optional.ofNullable(id);
    }

    public void setId(Integer id) {
        this.id = id;
    }

}
ledniov
  • 2,302
  • 3
  • 21
  • 27