0

我有一个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;
    }

序列化的 Json 字符串为 {"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 序列化器或反序列化器。

4

1 回答 1

2

好吧,也许异常消息不是很清楚,但实际发生的是你得到了一个被捕获的 StackOverFlow,而杰克逊却抛出了一个奇怪的KeyException。

The problem is your JsonCreator: you can't use the ObjectMapper in your method because that will simply call the JsonCreator again and again and again. What you should do instead is something like the following:

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

Update: Since it didn't appear to be clear I'll try to explain a bit more the control flow.

What happens in this case is that the databinding functionnality of Jackson (with ObjectMapper) gets called recursively. The fromJSON is called during databinding because it is annotated with JsonCreator; any time you try to create an instance of MyKey with Jackson that method will be called. So, when you try

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

Jackson will call fromJSON, because that's how it knows to create MyKey.

As a rule of thumb, I avoid using Jackson functionality inside of methods that have annotations for Jackson, that's just asking for trouble. When you do you need to be extra careful because of the implicit recursion like this one.

于 2012-08-24T15:38:07.943 回答