web/play-java-forms/src/main/java/play/data/format/Formatters.java
private Formatters registerOptional() {
    conversion.addConverter(
        new GenericConverter() {

          public Object convert(
              Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
            if (sourceType.getObjectType().equals(String.class)) {
              // From String to Optional
              Object element =
                  conversion.convert(source, sourceType, targetType.elementTypeDescriptor(source));
              return Optional.ofNullable(element);
            } else if (targetType.getObjectType().equals(String.class)) {
              // From Optional to String
              if (source == null) return "";

              Optional<?> opt = (Optional) source;
              return opt.map(
                      o ->
                          conversion.convert(
                              source, sourceType.getElementTypeDescriptor(), targetType))
                  .orElse("");
            }
            return null;
          }

          public Set<GenericConverter.ConvertiblePair> getConvertibleTypes() {
            Set<ConvertiblePair> result = new HashSet<>();
            result.add(new ConvertiblePair(Optional.class, String.class));
            result.add(new ConvertiblePair(String.class, Optional.class));
            return result;
          }
        });

    return this;
  }
private Formatters registerOptional() {
    conversion.addConverter(
        new GenericConverter() {

          public Object convert(
              Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
            if (sourceType.getObjectType().equals(String.class)) {
              // From String to Optional
              Object element =
                  conversion.convert(source, sourceType, targetType.elementTypeDescriptor(source));
              return Optional.ofNullable(element);
            } else if (targetType.getObjectType().equals(String.class)) {
              // From Optional to String
              if (source == null) return "";

              Optional<?> opt = (Optional) source;
              return opt.map(
                      o ->
                          conversion.convert(
                              source, sourceType.getElementTypeDescriptor(), targetType))
                  .orElse("");
            }
            return null;
          }

          public Set<GenericConverter.ConvertiblePair> getConvertibleTypes() {
            Set<ConvertiblePair> result = new HashSet<>();
            result.add(new ConvertiblePair(Optional.class, String.class));
            result.add(new ConvertiblePair(String.class, Optional.class));
            return result;
          }
        });

    return this;
  }
Converter for String -> Optional and Optional -> String