Json - 关键异常?

时间:2012-08-24 09:23:21

标签: java json jackson

我有LinkedHashMap<MyKey, MyValue>,MyKey和MyValue是POJO。

MyKey是一个拥有getter和setter的bean,它还覆盖了hashcode()方法。我在某地读过Map将使用对象的hashcode()来形成键,所以如果我从json写出来......它究竟是如何读取它的?

在MyKey中,我定义了以下功能:

@JsonCreator
    public static MyKey fromJSON(String val) throws JsonParseException, JsonMappingException, IOException {
        ObjectMapper mapper = new ObjectMapper();
        MyKey a = mapper.readValue(val,MyKey .class);
        return a;
    }

Serialized Json String的格式为{“MyKey @ 3”:{MyValue .. json string}}。

我正在跟踪异常跟踪:

at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
    at org.codehaus.jackson.map.deser.StdDeserializationContext.weirdKeyException(StdDeserializationContext.java:234)
    at org.codehaus.jackson.map.deser.StdKeyDeserializer.deserializeKey(StdKeyDeserializer.java:34)
    at org.codehaus.jackson.map.deser.MapDeserializer._readAndBind(MapDeserializer.java:223)
    at org.codehaus.jackson.map.deser.MapDeserializer.deserialize(MapDeserializer.java:165)
    at org.codehaus.jackson.map.deser.MapDeserializer.deserialize(MapDeserializer.java:25)
    at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:252)
    at org.codehaus.jackson.map.deser.SettableBeanProperty$MethodProperty.deserializeAndSet(SettableBeanProperty.java:356)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:494)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:368)
    at org.codehaus.jackson.map.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:77)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeWithType(BeanDeserializer.java:423)
    at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:250)
    at org.codehaus.jackson.map.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:595)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:472)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:368)
    at org.codehaus.jackson.map.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:77)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeWithType(BeanDeserializer.java:423)
    at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:250)
    at org.codehaus.jackson.map.deser.SettableBeanProperty$MethodProperty.deserializeAndSet(SettableBeanProperty.java:356)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:494)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:368)
    at org.codehaus.jackson.map.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:77)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeWithType(BeanDeserializer.java:423)
    at org.codehaus.jackson.map.deser.StdDeserializerProvider$WrappedDeserializer.deserialize(StdDeserializerProvider.java:460)
    at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2395)
    at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1595)

我该如何解决这个问题?如果可能的话,我宁愿不注册json序列化器或反序列化器。

1 个答案:

答案 0 :(得分:2)

好吧,也许Exception消息不是很清楚,但实际发生的是你得到一个被捕获的StackOverFlow而Jackson会抛出一个奇怪的KeyException。

问题是你的JsonCreator:你不能在你的方法中使用ObjectMapper,因为它只会一次又一次地调用JsonCreator。您应该做的事情如下:

@JsonCreator
public static MyKey fromJSON(String val) throws JsonParseException, JsonMappingException, IOException {
    return new MyKey(val);
}

更新:由于看起来不太清楚,我会尝试解释一下控制流程。

在这种情况下发生的事情是Jackson(带有ObjectMapper)的数据绑定功能被递归调用。在数据绑定期间调用fromJSON,因为它使用JsonCreator注释;每当你尝试用Jackson创建一个MyKey实例时,都会调用该方法。所以,当你尝试

MyKey a = mapper.readValue(val,MyKey .class);

杰克逊将从JSON打电话,因为它知道如何创建MyKey。

根据经验,我避免在杰克逊注释的方法中使用杰克逊功能,这只是在寻找麻烦。当你这样做时,你需要格外小心,因为像这样的隐式递归。