2013-03-26 82 views
0

好时机!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

它根本不清楚你需要编写一个自定义的解串器。事实上,使用Jackson POJO绑定会简单得多,而忽略额外的不需要的字段。如果您决定不管什么原因继续使用自定义反序列化器,那么您应该能够获取类型值,就像获取类别名称一样。您可能希望在问题中包含您当前的解串器代码。 – Perception 2013-03-26 11:36:53

+0

@Perception,其实我真的需要自定义的反序列化器,因为在构建Category对象时有一些事情要做。我已经添加了解串器代码。 – Dmitry 2013-03-26 12:07:43

回答

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();findTokenText方法里面的代码jp.getText()(刚刚试了一下在调试模式下)返回“C”,就好像读卡器没有复位一样。 有人可以解释,为什么会发生这种情况?

另一个变种是避免自定义和使用this后的建议。