如何在不通过ObjectMapper时在JsonParser上设置ObjectCodec?

注意:这是使用Jackson 2.3.2

为了满足我的一个项目的需要,我正在编写一个自定义的JsonParser ,它记录了一个Map ,其中键是JsonPointer ,值是Integer s(指针指向的行号)。

该类名为LineRecorderJsonParser 。 它由LineRecorderJsonFactory生成,它是一个简单的委托:

 public final class LineRecorderJsonFactory extends JsonFactory { @Override protected JsonParser _createParser(final InputStream in, final IOContext ctxt) throws IOException, JsonParseException { final JsonParser parser = super._createParser(in, ctxt); return new LineRecorderJsonParser(parser); } @Override protected JsonParser _createParser(final Reader r, final IOContext ctxt) throws IOException, JsonParseException { final JsonParser parser = super._createParser(r, ctxt); return new LineRecorderJsonParser(parser); } @Override protected JsonParser _createParser(final byte[] data, final int offset, final int len, final IOContext ctxt) throws IOException, JsonParseException { final JsonParser parser = super._createParser(data, offset, len, ctxt); return new LineRecorderJsonParser(parser); } } 

我已使用以下代码测试了代码的工作原理:

 public static void main(final String... args) throws IOException { final JsonFactory factory = new LineRecorderJsonFactory(); final ObjectMapper mapper = new ObjectMapper(factory); final Closer closer = Closer.create(); final InputStream in; try { in = closer.register(LineTesting.class.getResourceAsStream ("/testfile.json")); mapper.readTree(in); } finally { closer.close(); } } 

但现在我想测试一下; 所以我写了以下测试代码:

 public final class LineRecorderJsonParserTest { private static final String INCORRECT_LINE_INFO = "generated line info is incorrect; expected: %s, actual: %s"; private JsonFactory factory; private ObjectMapper mapper; @BeforeMethod public void initFactory() { factory = new LineRecorderJsonFactory(); mapper = new ObjectMapper(); } @DataProvider public Iterator getLineData() { final List list = Lists.newArrayList(); list.add(new Object[] { "1" }); return list.iterator(); } @Test(dataProvider = "getLineData") public void lineNumbersAreCorrectlyReported(final String subdir) throws IOException { final String basePath = "/parser/" + subdir + '/'; final Closer closer = Closer.create(); final TypeReference<Map> typeRef = new TypeReference<Map>() {}; final InputStream input, lines; final Map actual, expected; final LineRecorderJsonParser parser; try { input = closer.register(inputFrom(basePath + "input.json")); lines = closer.register(inputFrom(basePath + "lines.json")); expected = mapper.readValue(lines, typeRef); parser = (LineRecorderJsonParser) factory.createParser(input); //parser.setCodec(factory.getCodec()); // Doesn't change anything... parser.readValueAsTree(); // FAILS HERE actual = parser.getLineInfo(); assertEquals(actual, expected, String.format(INCORRECT_LINE_INFO, expected, actual)); } catch (IOException e) { throw closer.rethrow(e); } finally { closer.close(); } } private static InputStream inputFrom(final String path) { return LineRecorderJsonParserTest.class.getResourceAsStream(path); } } 

不幸的是,这不起作用。 我得到以下exception:

 java.lang.IllegalStateException: No ObjectCodec defined for the parser, can not deserialize JSON into JsonNode tree at com.fasterxml.jackson.core.JsonParser.readValueAsTree(JsonParser.java:1507) at com.fasterxml.jackson.core.util.JsonParserDelegate.readValueAsTree(JsonParserDelegate.java:371) at com.github.fge.jackson.parse.LineRecorderJsonParserTest.lineNumbersAreCorrectlyReported(LineRecorderJsonParserTest.java:84) 

即使我(尝试并且)自己设置了一个ObjectCodec (参见代码),我也得到了这个例外……

我究竟做错了什么? 我如何测试这个类,因为当你直接使用ObjectMapper读取时,你没有机会获取底层的解析器?

或者, JsonFactory.setCodec(mapper)

好吧,在我提出这个问题后,我发现如何做到这一点甚至几分钟……如果它对其他人有用,我会回答自己。

首先,我的JsonFactory.getCodec()返回null ; 如果您尝试将其提供给null编解码器, JsonParser不会对您大喊大叫。

其次, ObjectMapper扩展了ObjectCodec ,而ObjectCodec 有一个读取树的方法 (事实上​​,它通常包含你在ObjectMapper上使用的所有方法)。

因此,将代码更改为此工作:

 parser = (LineRecorderJsonParser) factory.createParser(input); mapper.readTree(parser); actual = parser.getLineInfo();