Skip to content

Instantly share code, notes, and snippets.

@mrbald
Created December 14, 2020 15:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrbald/4218ee3336dc9ccb8e7919f3245332c3 to your computer and use it in GitHub Desktop.
Save mrbald/4218ee3336dc9ccb8e7919f3245332c3 to your computer and use it in GitHub Desktop.
XStream XML Codec
project(":xstreamist") {
dependencies {
implementation 'com.thoughtworks.xstream:xstream:1.4.14'
implementation 'com.fasterxml.woodstox:woodstox-core:6.2.3'
implementation 'xpp3:xpp3:1.1.4c'
}
}
package xstreamist;
@XStreamAlias("my-msg")
public class MyXmlMessage {
// ...
};
package xstreamist;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.SingleValueConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.CompactWriter;
import com.thoughtworks.xstream.io.xml.Xpp3Driver;
import org.apache.commons.io.output.StringBuilderWriter;
import javax.annotation.Nullable;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.time.Duration;
import java.time.Instant;
public class XmlCodec {
private static final ThreadLocal<XStream> xStream = ThreadLocal.withInitial(XmlCodec::createXStream);
private static XStream createXStream() {
final XStream xs = new XStream(new Xpp3Driver() {
@Override
public HierarchicalStreamWriter createWriter(final Writer out) {
return new CompactWriter(out, getNameCoder());
}
});
setupDefaultSecurity(xs);
xs.allowTypesByWildcard(new String[]{"com.mycompany.**"});
// http://x-stream.github.io/graphs.html
xs.setMode(XStream.NO_REFERENCES);
xs.processAnnotations(MyXmlMessage.class);
xs.processAnnotations(MyAnotherXmlMessage.class);
return xs;
}
static XStream xStream() {
return xStream.get();
}
public static Object decode(String str) {
return xStream().fromXML(new StringReader(str));
}
public static String encode(Object obj) {
final StringBuilderWriter w = new StringBuilderWriter(256);
xStream().toXML(obj, w);
return w.toString();
}
public static final class InstantConverter implements SingleValueConverter {
@Override public @Nullable String toString(final Object obj) { return obj == null ? null : String.valueOf(((Instant)obj).toEpochMilli()); }
@Override public @Nullable Object fromString(final String str) { return str == null || str.isEmpty() ? null : Instant.ofEpochMilli(Long.parseLong(str)); }
@Override public boolean canConvert(final Class type) { return Instant.class == type; }
}
public static final class DurationConverter implements SingleValueConverter {
@Override public @Nullable String toString(final Object obj) { return obj == null ? null : String.valueOf(((Duration)obj).toMillis()); }
@Override public @Nullable Object fromString(final String str) { return str == null || str.isEmpty() ? null : Duration.ofMillis(Long.parseLong(str)); }
@Override public boolean canConvert(final Class type) { return Duration.class == type; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment