使用Jackson解析JSON时限制Map值

时间:2012-11-17 16:37:12

标签: java json jackson

我正在使用Jackson来解析JSON,其中一个字段是任意键和值的字典。如果我们只允许某些值类型(Map<String, Object>StringLongDouble,这通常会直接映射到Java Long[]Double[])。

目前我们完整地解析文档,然后遍历每个地图的每个值并执行instanceof以检查它是否有效,在无效时向用户返回错误。对于长文档而言,这当然是相当低效的,我们有很多文档。

是否有人知道如何向杰克逊表达此地图值类型限制,以便在解析过程中可以捕获输入中的任何错误? @JsonSubTypes注释看起来可能相关,但无法确定在这种情况下如何应用它。

以下是我想要替换的代码类型的示例:

static class Doc {
    List<Item> items;
}

static class Item {
    /* ...other fields snipped... */
    public Map<String, Object> payload;

    @JsonIgnore
    public void check() throws Exception {
        for(Object value: item.payload.values()) {
            if(value instanceof String) { 
            else if(value instanceof Long) { }
            else if(value instanceof Long[]) { }
            else if(value instanceof Double) { }
            else if(value instanceof Double[]) { }
            else { throw new Exception("Unsupported value type"); }
        }
    }
}

void read(InputStream stream) throws Exception {
    ObjectMapper mapper = new ObjectMapper();
    Doc doc = mapper.readValue(stream, Doc.class);

    // Check all payload types are valid
    for(Item item: doc.items) {
        item.check()
    }
}

2 个答案:

答案 0 :(得分:1)

好吧,找不到使用杰克逊提供的注释或类型系统表达我想要的方法,所以我最后通过编写自定义反序列化器来做我想避免的事情。

不可否认,这确实允许对允许的数据类型和解析错误进行更简洁的控制,但它比我想要的更冗长!

答案 1 :(得分:1)

没有特定功能可以执行此操作,但如何创建针对不可接受的子类型抛出异常的Map子类?类似的东西:

public class LimitedMap extends HashMap<String,Object> {
  public Object put(String key, Object value) {
     // verify it's not a Boolean or Map. And note that Jackson uses List
     // for JSON Arrays; Double for floating point (by default), Integer or Long for ints
  }
} 

另一种方法是使用JSON Schema验证器(其中许多都建立在杰克逊身上)。