【发布时间】:2014-09-10 00:58:59
【问题描述】:
我有一个带有映射器的 Map-Reduce 作业,它获取一条记录并将其转换为一个对象,即 MyObject 的一个实例,它使用 Jackson 编组为 JSON。该值只是记录中的另一个文本字段。
映射器的相关部分如下所示:
ObjectMapper mapper = new ObjectMapper();
MyObject val = new MyObject();
val.setA(stringA);
val.setB(stringB);
Writer strWriter = new StringWriter();
mapper.writeValue(strWriter, val);
key.set(strWriter.toString());
映射器的输出被发送到一个组合器,它解组 JSON 对象并聚合键值对。它在概念上非常简单,类似于:
public void reduce(Text key, Iterable<IntWritable> values, Context cxt)
throws IOException, InterruptedException {
int count = 0;
TermIndex x = _mapper.readValue(key.toString(), MyObject.class);
for (IntWritable int : values) ++count;
...
emit (key, value)
}
MyObject 类由两个字段(均为字符串)、get/set 方法和一个默认构造函数组成。其中一个字段存储基于网络爬取的文本的 sn-ps,但始终是字符串。
public class MyObject {
private String A;
private String B;
public MyObject() {}
public String getA() {
return A;
}
public void setA(String A) {
this.A = A;
}
public String getB() {
return B;
}
public void setIdx(String B) {
this.B = B;
}
}
我的 MapReduce 作业似乎运行良好,直到它到达某些我无法轻松访问的记录(因为映射器正在通过爬网生成记录),并且引发了以下异常:
Error: com.fasterxml.jackson.core.JsonParseException:
Illegal character ((CTRL-CHAR, code 0)): only regular white space (\r, \n, \t) is allowed between tokens
at [Source: java.io.StringReader@5ae2bee7; line: 1, column: 3]
有人对造成这种情况的原因有什么建议吗?
【问题讨论】:
-
使用 okhttp 1.5.1。希望它能解决您的问题。
-
我知道您说您无法轻松访问,但我建议前端抓取并从流中删除虚假控制字符,例如 0 (NULL),然后将其传递给 jackson。我已经看到各种证券的财务提要有这样的虚假数据,总是需要剔除。这很可能是发送方的缺陷。
-
在低级别,某些东西正在将空字节(字节 0)注入流中,而解析器不接受这些(它们对 JSON 无效)。您需要弄清楚这是如何以及为什么会发生的;这可能是很多事情,包括并发问题或时间(尝试在内容加载到缓冲区之前解析内容)。
-
如果可能,添加几行日志,这样您就可以看到哪些记录确实失败了。此外,由于您正在抓取数据,因此您可能会遇到与此处相同的问题(GZip 编码):stackoverflow.com/questions/8091524/…
标签: java json hadoop jackson marshalling