Java 当不通过 ObjectMapper 时,如何在 JsonParser 上设置 ObjectCodec?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22870488/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you set an ObjectCodec on a JsonParser when not going through an ObjectMapper?
提问by fge
Note: this is using Hymanson 2.3.2
注意:这是使用 Hymanson 2.3.2
For the needs of one of my projects, I am writing a custom JsonParser
which records a Map
where keys are JsonPointer
s and values are Integer
s (line numbers where the pointer points to).
为了我的一个项目的需要,我正在编写一个自定义JsonParser
记录,Map
其中键是JsonPointer
s,值是Integer
s(指针指向的行号)。
The class is named LineRecorderJsonParser
. It is produced by a LineRecorderJsonFactory
which is a simple delegate:
该类名为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);
}
}
I have tested that the code works using the following code:
我已经使用以下代码测试了该代码是否有效:
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();
}
}
But now I want to test it; so I wrote the following test code:
但现在我想测试一下;所以我写了以下测试代码:
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<Object[]> getLineData()
{
final List<Object[]> 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<JsonPointer, Integer>> typeRef
= new TypeReference<Map<JsonPointer, Integer>>() {};
final InputStream input, lines;
final Map<JsonPointer, Integer> 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);
}
}
Unfortunately this doesn't work. I get the following exception:
不幸的是,这不起作用。我收到以下异常:
java.lang.IllegalStateException: No ObjectCodec defined for the parser, can not deserialize JSON into JsonNode tree
at com.fasterxml.Hymanson.core.JsonParser.readValueAsTree(JsonParser.java:1507)
at com.fasterxml.Hymanson.core.util.JsonParserDelegate.readValueAsTree(JsonParserDelegate.java:371)
at com.github.fge.Hymanson.parse.LineRecorderJsonParserTest.lineNumbersAreCorrectlyReported(LineRecorderJsonParserTest.java:84)
Even when I (try and) set an ObjectCodec
myself (see code), I get this exception...
即使我(尝试和)设置了ObjectCodec
自己(见代码),我也会得到这个例外......
What am I doing wrong? How can I test this class, since when you read using an ObjectMapper
directly, you don't get a chance to grab the underlying parser?
我究竟做错了什么?我如何测试这个类,因为当您ObjectMapper
直接使用 an 读取时,您没有机会获取底层解析器?
回答by fge
Well, I found out how to do that not even minutes after I asked the question... I'll answer to self should it prove useful for other people.
好吧,我在问这个问题几分钟后就发现了如何做到这一点......如果它对其他人有用,我会回答自己。
First of all, my JsonFactory
's .getCodec()
returned null
; and JsonParser
doesn't yell at you if you try and feed it a null codec.
首先,我JsonFactory
的.getCodec()
恢复null
; 而JsonParser
如果你试着给它一个空编解码器不骂你。
Second, ObjectMapper
extends ObjectCodec
, and ObjectCodec
has a method to read a tree(it has, in fact, all methods you customarily use on an ObjectMapper
).
其次,ObjectMapper
extends ObjectCodec
,并且ObjectCodec
有一种读取树的方法(实际上,它具有您通常在 上使用的所有方法ObjectMapper
)。
Therefore, changing the code to this worked:
因此,将代码更改为此有效:
parser = (LineRecorderJsonParser) factory.createParser(input);
mapper.readTree(parser);
actual = parser.getLineInfo();
回答by StaxMan
Or, JsonFactory.setCodec(mapper)
.
或者,JsonFactory.setCodec(mapper)
。