Comments (7)
Source files:
Renderer.java
interface Renderer {
// empty
}
CircleRenderer.java
class CircleRenderer implements Renderer {
// empty
}
Table.java
import java.util.LinkedHashMap;
import java.util.Map;
class Table {
private Map<String, Renderer> renderers = new LinkedHashMap<>();
Table() {
// empty
}
Map<String, Renderer> getRenderers() {
return new LinkedHashMap<>(renderers);
}
void setRenderer(String column, Renderer renderer) {
renderers.put(column, renderer);
}
}
TableConverter.java
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import java.util.Map;
class TableConverter implements Converter {
private String lastNodeName = null;
TableConverter() {
// empty
}
@Override
public boolean canConvert(Class clazz) {
return Table.class.equals(clazz);
}
String getLastNodeName() {
return lastNodeName;
}
@Override
public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
Table table = (Table) value;
writer.startNode("renderers");
context.convertAnother(table.getRenderers());
writer.endNode();
}
@Override
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
Table table = new Table();
reader.moveDown();
try {
unmarshalRenderers(reader, context, table);
} catch (ConversionException e) {
// log exception
} finally {
reader.moveUp();
}
lastNodeName = reader.getNodeName();
return table;
}
private void unmarshalRenderers(HierarchicalStreamReader reader, UnmarshallingContext context, Table table) {
assert reader.getNodeName().equals("renderers");
Map<String, Renderer> renderers = (Map<String, Renderer>) context.convertAnother(null, Map.class);
for (Map.Entry<String, Renderer> entry : renderers.entrySet()) {
table.setRenderer(entry.getKey(), entry.getValue());
}
}
}
from xstream.
Test:
TableConverterTest.java
import static org.junit.Assert.*;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
public class TableConverterTest {
private XStream xstream;
private TableConverter converter;
@Before
public void setUp() {
xstream = new XStream();
converter = new TableConverter();
xstream.registerConverter(converter);
}
@Test
public void testMarshal() {
final Table table = new Table();
table.setRenderer("foo", new CircleRenderer());
table.setRenderer("bar", new CircleRenderer());
assertEquals(
"<Table>\n" +
" <renderers>\n" +
" <entry>\n" +
" <string>foo</string>\n" +
" <CircleRenderer/>\n" +
" </entry>\n" +
" <entry>\n" +
" <string>bar</string>\n" +
" <CircleRenderer/>\n" +
" </entry>\n" +
" </renderers>\n" +
"</Table>",
xstream.toXML(table)
);
}
@Test
public void testUnmarshalWithCircleRenderer() {
xstream.fromXML(
"<Table>\n" +
" <renderers>\n" +
" <entry>\n" +
" <string>foo</string>\n" +
" <CircleRenderer/>\n" +
" </entry>\n" +
" </renderers>\n" +
"</Table>"
);
assertEquals("Table", converter.getLastNodeName());
}
@Test
public void testUnmarshalWithSquareRenderer() {
xstream.fromXML(
"<Table>\n" +
" <renderers>\n" +
" <entry>\n" +
" <string>foo</string>\n" +
" <SquareRenderer/>\n" + // doesn't exist
" </entry>\n" +
" </renderers>\n" +
"</Table>"
);
assertEquals("Table", converter.getLastNodeName());
}
}
from xstream.
POM:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>issue-26</artifactId>
<version>0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<targetJdk>1.7</targetJdk>
</properties>
<dependencies>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.8</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<defaultGoal>test</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${targetJdk}</source>
<target>${targetJdk}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
from xstream.
The input stream is for XStream in an undefined state after an exception. XStream does not make any agreements after an exception is raised.
Any converter (not only XStream's) would have to obey a contract that an even call of the moveDown/moveUp have been made at the exit of the unmarshal method.
from xstream.
What you can do instead is to derive a custom converter from MapConverter and overload putCurrentEntryIntoMap that can ignore the exception adds no element to the map in that case.
from xstream.
Thanks for your quick reply Jörg.
I understand in the general case when you don't really know what converters you're working with there's basically nothing you can do short of maybe creating a separate XStream instance and trying to serialize it out separately beforehand.
That being said, do you think there would still be value in making XStream's stock map converter (and maybe others) at least make a best effort to recover?
I'm working on a contract right now where the customer needs to be able to recover from missing items in the input file, and we will probably just put in a separate check before like I mentioned to be sure, or in this specific case just serialize the items out differently.
However, I was thinking there may be others that come along who might find it helpful if they didn't have to do anything extra, especially if they're only working with the stock XStream converters.
Or do you think that having the XStream converters recover would potentially be misleading?
from xstream.
I am a bit hesitant to improve the situation, because XStream will never be able to guarantee something. Basically, XStream is Java to XML and back, i.e. normally is never something unknown in the XML. ;-)
However, for your special case, I'd really register a custom MapConverter with the modification proposed above. For fields you may use omitField or ignoreUnknownElements, unfortunately these settings do not apply to elements of lists or maps.
from xstream.
Related Issues (20)
- Unable to serialize Oracle DB objects using xstream HOT 3
- XStream Core latest version 1.4.19 is vulnerable HOT 1
- We have requested that one will remain for woodstox (CVE-2022-40152), and that the duplicates (CVE-2022-40153, CVE-2022-40154, CVE-2022-40155 and CVE-2022-40156) will be deleted. Those using Woodstox in Xstream have DTD support enabled by default, at least that's the way how the vulnerability in woodstox was found, see [Xstream fuzz target](https://github.com/google/oss-fuzz/blob/master/projects/xstream/XmlFuzzer.java). HOT 1
- The class `SerializationMembers` can not be used in `native-image`.
- Any plans to support GraalVM Native Image? HOT 4
- Using xStream_1_4_20, Not able to convert AtomicReference atomicRef = new AtomicReference(); with default value. It is giving NullpointerException. HOT 1
- Illegal reflective access by com.thoughtworks.xstream.converters.reflection.FieldDictionary HOT 1
- unable to deserialize to object HOT 2
- Convert in mother class won't work HOT 2
- XStreamOmitField default value HOT 1
- how to remove the class attribute when serializing Java Bean to xml? HOT 1
- `PrettyPrintWriter` cannot write emoji in XML 1.1 mode HOT 1
- how to parse xml string into class with genericity HOT 3
- How to set byte array not to do conversion?Thanks. HOT 1
- Unmodifiable Lists converter HOT 1
- how both text and sub tags exist HOT 3
- DomReader: slow performance $O(n^2)$ when deserialize on millions of elements to list HOT 3
- B
- Is there any annotations can support both attribute and sub tags HOT 1
- Support Record Classes HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from xstream.