2014-10-10 85 views
2

我有一種POJO擴展抽象超類的情況,它使用java.io.Serializable類型(如下所示)定義類似getId()setId()的方法。每當我反序列化JSON字符串我具體的POJO,我得到以下異常:我怎樣才能使用傑克遜映射器的java.io.Serializable類型字段?

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.io.Serializable, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information 
at [Source: [email protected]; line: 1, column: 2] (through reference chain: com.demo.jackson.AClass["id"]) 
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164) 
    at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:716) 
    at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:140) 
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:525) 
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:99) 
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:242) 
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:118) 
    at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1270) 
    at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:897) 

如Java代碼:

摘要超類

public abstract class AbstractClass { 
    protected abstract void setId(final Serializable id); 
    protected abstract Serializable getId(); 
} 

實現類:AClass

public class AClass extends AbstractClass { 
    private Long id; 
    private String name; 

    public Long getId() { 
    return id; 
    } 
    public void setId(Serializable id) { 
    this.id = (Long) id; 
    } 
    public String getName() { 
    return name; 
    } 
    public void setName(String name) { 
    this.name = name; 
    } 
} 

實現類:BClass

public class BClass extends AbstractClass { 
    private String id; 
    private String name; 

    public String getId() { 
    return id; 
    } 
    public void setId(Serializable id) { 
    this.id = (String) id; 
    } 
    public String getName() { 
    return name; 
    } 
    public void setName(String name) { 
    this.name = name; 
    } 
} 

測試類

public class JsonSerializerTest { 
    public static void main(String[] args) throws Exception { 
    final ObjectMapper objectMapper = new ObjectMapper(); 
    serialize(objectMapper); 
    } 

    private static void serialize(final ObjectMapper objectMapper) throws Exception { 
    final String jsonString = "{\"id\":123,\"name\":\"AClass\"}"; 
    final ObjectReader objectReader = objectMapper.reader(AClass.class); 
    final AClass a = objectReader.readValue(jsonString); 
    System.out.println(a); 
    } 
} 

有人可以提供一些指點?

〜NN

+0

我不認爲可序列化的是一種類型的,它的一個接口。你的抽象getid是可序列化的類型,但是你的具體方法是long型的 – chiliNUT 2014-10-10 19:11:11

+0

是的,我意識到這一點,這是設計的東西。我們的框架團隊提供了這樣的接口和抽象類,而實現則由應用程序開發團隊提供。 – Niranjan 2014-10-10 20:07:06

回答

0

我不知道你有什麼選擇,但對超載的子類setId方法是什麼然後做出傑克遜忽略那些接受Serializable

所以,ClassA應該是這樣的:

public class AClass extends AbstractClass { 
    private Long id; 
    private String name; 

    public Long getId() { 
     return id; 
    } 
    @JsonIgnore 
    public void setId(Serializable id) { 
     this.id = (Long) id; 
    } 
    public void setId(Long id) { 
     this.id = id; 
    } 
    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 
} 

該解決方案是不是太優雅,但它可能是你可以接受的。如果不是,我建議檢查傑克遜的custom serialization和/或polymorphic serialization支持。

+0

謝謝你,但我恐怕這不會工作,因爲@ JsonIgnore是忽略該屬性。所以,通過這種方法,在反序列化過程中我的ID值不會被填充。讓我看一下你提供的鏈接。我曾見過這些自定義和多態的序列化,但不知何故,我沒有找到類似於我的問題的好例子。 – Niranjan 2014-10-10 20:09:13

+0

好吧,但看看關於JsonIgnore的重載方法這個問題:http://stackoverflow.com/questions/6346018/deserializing-json-into-object-with-overloaded-methods-using-jackson – Katona 2014-10-10 20:54:17

1

爲我們工作的解決方案如下所示。

Abstract Class:使用Object而不是Serializable。我知道Serializable更適合ID,但這個問題對我們的應用來說是一種阻礙,我們選擇了這種解決方案。

public abstract class AbstractClass { 
    protected abstract void setId(final Object id); 
    protected abstract Object getId(); 
} 

實現:AClass

public class AClass extends AbstractClass { 
    private Long id; 
    private String name; 

    public Long getId() { 
    return id; 
    } 
    public void setId(Object id) { 
    // We need this inverted way to get a Long from a String, but we didn't have any other option! 
    this.id = Long.valueOf(Objects.toString(id)); 
    } 
    public String getName() { 
    return name; 
    } 
    public void setName(String name) { 
    this.name = name; 
    } 
} 

實現:BClass

public class BClass extends AbstractClass { 
    private String id; 
    private String name; 

    public String getId() { 
    return id; 
    } 
    public void setId(Object id) { 
    this.id = Objects.toString(id); 
    } 
    public String getName() { 
    return name; 
    } 
    public void setName(String name) { 
    this.name = name; 
    } 
} 

我不知道如果這是一個完美的解決方案或沒有(影響()序列化呢?對象),但請隨時發佈一個更好的。

謝謝。

〜NN

3

我們有同樣的情況,我們必須使用java.io.可以在實體中作爲ID序列化。使用序列化我們沒有問題,但在反序列化中,我們遇到了問題。在我們的應用程序中,我們在JOSN對象中使用了String,所以Stdandard StringDeserializer和它正在工作 - 理論上你可以在任何Serializable實現中使用它。 (阿帕奇CXF和Jackson 2.4.1使用):

初始化傑克遜提供商:

// Jackson JSON Provider 
    ObjectMapper mapper = new ObjectMapper(); 
    mapper.registerModule(new IdentifiableDeserializableModule()); 

    JacksonJaxbJsonProvider jp = new JacksonJaxbJsonProvider(mapper, JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS); 
    jp.configure(SerializationFeature.INDENT_OUTPUT, indentJson); 

和模塊:

import com.fasterxml.jackson.databind.deser.std.StringDeserializer; 
import com.fasterxml.jackson.databind.module.SimpleModule; 

import java.io.Serializable; 

/** 
* Jackson module to deserialize java.io.Serializable class. 
*/ 
public class IdentifiableDeserializableModule extends SimpleModule { 
    public IdentifiableDeserializableModule() { 
     addDeserializer(Serializable.class, new StringDeserializer()); 
    } 
}