Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support java.util.Optional #294

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion xstream/src/java/com/thoughtworks/xstream/XStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.SortedSet;
Expand Down Expand Up @@ -154,6 +155,7 @@
import com.thoughtworks.xstream.converters.extended.JavaMethodConverter;
import com.thoughtworks.xstream.converters.extended.LocaleConverter;
import com.thoughtworks.xstream.converters.extended.LookAndFeelConverter;
import com.thoughtworks.xstream.converters.extended.OptionalConverter;
import com.thoughtworks.xstream.converters.extended.PathConverter;
import com.thoughtworks.xstream.converters.extended.RegexPatternConverter;
import com.thoughtworks.xstream.converters.extended.SqlDateConverter;
Expand Down Expand Up @@ -712,7 +714,7 @@ protected void setupSecurity() {
final Set<Class<?>> types = new HashSet<>();
types.addAll(Arrays.<Class<?>>asList(BitSet.class, Charset.class, Class.class, Currency.class, Date.class,
DecimalFormatSymbols.class, File.class, Locale.class, Object.class, Pattern.class, StackTraceElement.class,
String.class, StringBuffer.class, StringBuilder.class, URL.class, URI.class, UUID.class));
String.class, StringBuffer.class, StringBuilder.class, URL.class, URI.class, UUID.class, Optional.class));
if (JVM.isSQLAvailable()) {
types.add(JVM.loadClassForName("java.sql.Timestamp"));
types.add(JVM.loadClassForName("java.sql.Time"));
Expand Down Expand Up @@ -801,6 +803,7 @@ protected void setupAliases() {
alias("bit-set", BitSet.class);
alias("trace", StackTraceElement.class);
alias("currency", Currency.class);
alias("optional", Optional.class);

alias("map", Map.class);
alias("entry", Map.Entry.class);
Expand Down Expand Up @@ -949,6 +952,7 @@ protected void setupConverters() {
registerConverter(new BigDecimalConverter(), PRIORITY_NORMAL);
registerConverter(new PathConverter(), PRIORITY_NORMAL);

registerConverter(new OptionalConverter(mapper), PRIORITY_NORMAL);
registerConverter(new ArrayConverter(mapper), PRIORITY_NORMAL);
registerConverter(new CharArrayConverter(), PRIORITY_NORMAL);
registerConverter(new CollectionConverter(mapper), PRIORITY_NORMAL);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (C) 2022 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
* style license a copy of which has been included with this distribution in
* the LICENSE.txt file.
*
* Created on 8. May 2022.
*/
package com.thoughtworks.xstream.converters.extended;

import java.util.Optional;

import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.core.util.HierarchicalStreams;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.mapper.Mapper;


/**
* Converts an {@link Optional}.
*/
public class OptionalConverter implements Converter {

private final Mapper mapper;

public OptionalConverter(final Mapper mapper) {
this.mapper = mapper;
}

public boolean canConvert(Class<?> type){
return type != null && type == Optional.class;
}

public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
final Optional<?> optional = (Optional<?>) source;

if (optional.isPresent()) {
Object item = optional.get();
String name = mapper.serializedClass(item.getClass());

writer.startNode(name);
context.convertAnother(item);
writer.endNode();
} else {
final String name = mapper.serializedClass(null);
writer.startNode(name);
writer.endNode();
}
}

public Optional<?> unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
reader.moveDown();
final Class<?> type = HierarchicalStreams.readClassType(reader, mapper);
Object item = context.convertAnother(null, type);
reader.moveUp();

return Optional.ofNullable(item);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.thoughtworks.xstream.converters.extended;

import java.util.Optional;

import com.thoughtworks.acceptance.AbstractAcceptanceTest;

public class OptionalConverterTest extends AbstractAcceptanceTest {

public void testEmpty() {
String expected =
"<optional>\n" +
" <null/>\n" +
"</optional>";

assertBothWays(Optional.empty(), expected);
}

public void testWithStringValue() {
String expected =
"<optional>\n" +
" <string>hi</string>\n" +
"</optional>";


assertBothWays(Optional.of("hi"), expected);
}

public void testWithIntValue() {
String expected =
"<optional>\n" +
" <int>1</int>\n" +
"</optional>";


assertBothWays(Optional.of(1), expected);
}
}