目标是学习如何将CSV读取到地图列表,然后学习如何将其编组为JSON。
一旦我理解了如何做到这一点,我将了解如何定义更多有用的路线。
我使用XML来定义路由,另一个限制不是创建任何转换bean,而只使用现有的组件。
我的理解显然缺乏一些概念。我知道你必须提供一个bean作为消费者,然后你可以传递它;但是文档说csv dataformat使用的地图列表有什么问题?
<dataFormats>
<json id="jack" library="Jackson"/>
</dataFormats>
<route>
<from uri="file:///C:/tries/collApp/exchange/in?fileName=registerSampleSmaller.csv"/>
<unmarshal>
<csv />
</unmarshal>
<marshal ref="jack">
</marshal>
<to uri="file:///C:/tries/collApp/exchange/out?fileName=out.json"/>
</route>
默默无所作为。我只能看到锁文件是如何出现和消失的。
谢谢!
ps /我期待创建两个路由,第一个将读取一个csv,转换它 - 将它的平面性质塑造成我的持久性bean,而不是传递给我的bean。而第二个只是将我的豆子保存为json,似乎是一个简单的部分;但我首先需要这样做以了解它是如何工作的
答案 0 :(得分:1)
请看一下这个DataFormat页面[1] 您可以使用那些编组DSL将对象转换为您想要的格式的String。 [1] http://camel.apache.org/data-format.html
答案 1 :(得分:1)
为什么要列出地图?为什么不列出名单?
如果您需要代码示例,请告诉我。但主要的想法是在解开csv之后总是检查身体。你很可能会得到一个pojo列表。然后只需迭代列表,并为每个pojo获取“getters”并设置json标记的值。
答案 2 :(得分:1)
我提出了一个答案,因为我向前迈进了一步。
我走在正确的轨道上,只有很小的错误。 JérémieB在对原始问题的评论中注意到了一个。
它无声地失败因为我没有启用日志记录,我是通过在我的pom.xml中添加这样的slf4j来实现的:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>${slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j-version}</version>
</dependency>
我看到了很多错误,甚至是Camel越野行为,但我已经设法让这条路线起作用了:
<dataFormats>
<json id="jack" library="Jackson" prettyPrint="true"/>
</dataFormats>
<route>
<from uri="file:///C:/tries/collApp/exchange/in?fileName=registerSampleUtf.csv&charset=UTF-8"/>
<log message="file: ${body.class.name} ${body}" loggingLevel="WARN"/>
<unmarshal>
<csv delimiter=";" useMaps="true" />
</unmarshal>
<log message="unmarshalled: ${body.class.name} ${body}" loggingLevel="WARN"/>
<marshal ref="jack"/>
<log message="marshalled: ${body}" loggingLevel="WARN"/>
<to uri="file:///C:/tries/collApp/exchange/out?fileName=out.json"/>
</route>
所以基本上,在清理错别字后我不得不
指定输入文件字符集,
指定Excel用于创建csv的分隔符,
告诉将其放入地图。
不幸的是,这个特定的代码不起作用,可能是由于我向开发者社区报告的Camel错误(还没有反应,http://camel.465427.n5.nabble.com/A-possible-bug-in-IOConverter-with-Win-1251-charset-td5778665.html)
虽然我向前迈进,但现在我可能绕过了有缺陷的Camel的IOConverter,目前我正处于这个阶段(这不是问题的答案,只是为了信息,Camel有多方便):
<route>
<from uri="file:///C:/tries/collApp/exchange/in?fileName=registerSampleSmaller1.csv&charset=windows-1251"/>
<split streaming="true">
<method ref="csvSplitter" method="tokenizeReader"/> <!-- aprepends the first line of file for every subsequent line -->
<log message="splitted: ${body}" loggingLevel="DEBUG"/>
<unmarshal>
<csv delimiter=";" useMaps="true" />
</unmarshal>
<log message="unmarshalled: size: ${body.size()}, ${body}" loggingLevel="DEBUG"/>
<filter>
<simple>${body.size()} == 1</simple><!-- be sure to have spaces around an operator -->
<log message="filtered: listItem: ${body[0]['PATRONYMIC']}, list: ${body}" loggingLevel="DEBUG"/>
<transform>
<spel>#{
{
lastName:body[0]['LAST_NAME'],
firstName: body[0]['FIRST_NAME'],
patronymic: body[0]['PATRONYMIC'],
comment:body[0]['COMMENT6']
}
}</spel><!-- split the spel {:} map creation notation in multiline is crucial-->
</transform>
<log message="transformed: ${body}" loggingLevel="DEBUG"/>
<marshal ref="jack"/>
<log message="marshalled: ${body}" loggingLevel="DEBUG"/>
<to uri="file:///C:/tries/collApp/exchange/out?fileName=out${exchangeProperty.CamelSplitIndex}.json"/>
</filter>
</split>
</route>
我必须编写自己的CSV分割器(关于所有Unicode代码点等),这基本上将第一行添加到所有后续行,但现在我能够以流畅的方式将CSV分成一组JSON ,或以不同方式处理对象而不是编组。
** update - csvSplitter code **
Reader Tokenizer - 读者周围的迭代器:
public class ReaderTokenizer implements Iterator<String> {
private String _curString = null;
private boolean _endReached = false;
private final Reader _reader;
private char[] _token;
public ReaderTokenizer(Reader reader, String token) {
setToken(token);
_reader = reader;
}
public final void setToken(String token){
_token = token.toCharArray();
if(_token.length==0){
throw new IllegalArgumentException("Can't tokenize with the empty string");
}
}
private void _readNextToken() throws IOException {
int curCharInt;
char previousChar = (char) -1;
int tokenPos = 0;
StringBuilder sb = new StringBuilder(255);
while (true) {
curCharInt = _reader.read();
if (curCharInt == -1) {
_endReached = true;
_reader.close();
break;
}
if (curCharInt == _token[tokenPos]) {
if (tokenPos != 0 || !Character.isHighSurrogate(previousChar)) {
tokenPos++;
if (tokenPos >= _token.length) {
tokenPos = 0;
previousChar = (char) curCharInt;
sb.append(previousChar);
break;
}
}
}
previousChar = (char) curCharInt;
sb.append(previousChar);
}
_curString = sb.toString();
}
@Override
public boolean hasNext() {
if (_curString == null) {
if (_endReached) {
return false;
}
try {
_readNextToken();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
if (_curString != null) {
return true;
}
if (_endReached) {
return false;
}
throw new RuntimeException("Someting wrong");
} else {
return true;
}
}
@Override
public String next() {
if (_curString != null) {
String ret = _curString;
_curString = null;
return ret;
}
if (_endReached) {
throw new NoSuchElementException();
}
try {
_readNextToken();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
if (_curString != null) {
String ret = _curString;
_curString = null;
return ret;
}
throw new RuntimeException("Someting wrong");
}
@Override
public void remove() {
throw new UnsupportedOperationException("Not supported.");
}
}
分裂器本身:
public class CamelReaderSplitter {
private final String _token;
private final int _headerLinesNumber;
public CamelReaderSplitter(String token, int headerLinesNumber) {
_token = token;
_headerLinesNumber = headerLinesNumber;
}
public CamelReaderSplitter(String token) {
_token = token;
_headerLinesNumber = 1;
}
public CamelReaderSplitter(int headerLinesNumber) {
_token = "\r\n";
_headerLinesNumber = headerLinesNumber;
}
public CamelReaderSplitter() {
_token = "\r\n";
_headerLinesNumber = 1;
}
public Iterator<String> tokenizeReader(final Reader reader) throws IOException {
Iterator<String> ret = new ReaderTokenizer(reader, _token) {
private final String _firstLines;
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < _headerLinesNumber; i++) {
if (super.hasNext()) {
sb.append(super.next());
}
}
_firstLines = sb.toString();
}
@Override
public String next() {
return _firstLines + super.next();
}
};
return ret;
}
}