杰克逊:在自定义反序列化器中获取任意节点的值

时间:2013-03-26 11:28:15

标签: java json jackson

美好时光!

说,有一个json字符串:{id:'a', type:'b', category:'c'},业务逻辑是这样的,以构建一个类别对象,我需要知道类别名称('c')和类型('b') 。显然我需要为类别编写自定义反序列化器(@JsonDeserialize(using = CategoryCustomDeserializer.class)),并且获取类别的名称很简单,但我无法弄清楚如何获取类型的值...我试过这个:jsonParser.getCodec().readTree(jsonParser),但会返回null

请建议正确的方法。

修改: 这是解串器:

  public class CategoryNameDeserializer extends JsonDeserializer<Category> {

     @Override
     public Category deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        if (jp.getCurrentToken() != JsonToken.END_OBJECT) {
           String categoryName = jp.getText();
           String type = ?????? <------------------------ How to do it
           return Service.getInstance().getCategory(categoryName, type);
        }

        return null;
  }
}

1 个答案:

答案 0 :(得分:0)

好吧,我找到了答案。这是一种解决方法,但它有效。可以使用以下方法重置解析器:

private JsonParser getResetParser(JsonParser jp) throws IOException {
    JsonFactory factory = jp.getCodec().getFactory();

    StringReader inputSource = (StringReader) jp.getInputSource();
    inputSource.reset();

    BufferedReader br = new BufferedReader(inputSource);
    String source = br.readLine();

    return factory.createJsonParser(source);
}

然后:

private String findTokenText(JsonParser jp, String fieldName) throws IOException {
    JsonParser parser = getResetParser(jp);
    while (true) {
        parser.nextToken();
        if (parser.hasCurrentToken()) {
            switch (parser.getCurrentToken()) {
                case END_ARRAY:
                case END_OBJECT:
                case NOT_AVAILABLE:
                case START_ARRAY:
                case START_OBJECT:
                case VALUE_EMBEDDED_OBJECT:
                case VALUE_FALSE:
                case VALUE_NUMBER_FLOAT:
                case VALUE_NUMBER_INT:
                case VALUE_TRUE:
                    // do nothing
                    break;
                case FIELD_NAME:
                    String currentName = parser.getCurrentName();
                    if (fieldName.equals(currentName)) {
                        parser.nextToken();
                        return parser.getText();
                    }
                    break;
            }
        } else {
            return null;
        }
    }

我不理解的是为什么尽管在inputSource.reset();方法中执行jp.getText()代码findTokenText(只是在调试模式下尝试过),但返回“C”,就好像读者没有重置。 任何人都可以解释一下,为什么会这样?

另一种变体是避免自定义并使用this帖子中的建议。