2015-05-19 72 views
4

我使用jackson 2將json轉換爲java對象。到現在爲止還挺好。但我也使用hazelcast將對象分佈在集羣中。因此所有的bean必須是java.io.Serializable。當我從JSON讀取對象,像這樣:由於傑克遜的Java二進制序列化失敗

ObjectMapper mapper = new ObjectMapper(); 
mapper.addMixInAnnotations(AbstractBean.class, MongoIdMixIn.class); 

// this is to prevent from failing on missing type class property: @JsonProperty("@class") 
Object tgtObject = targetClass.newInstance(); 
mapper.readerForUpdating(tgtObject).readValue(dbo.toString()); 

// put into hazelcast map 
target.put(dbo.get(keyColumn), tgtObject); 

我將從hazelcast得到一個異常:

java.io.NotSerializableException: com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer 

我想知道其中com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer來自於Object是一個普通的java bean(但使用繼承)。

我的抽象類是:

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) 
@JsonIgnoreProperties(ignoreUnknown = true) 
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@javaClass") 
public abstract class AbstractBean implements Serializable { 
    @JsonIgnore public static final transient IMarkupParser MARKUP_PARSER = new WikiMarkupParser(); 

    @JsonProperty("id") 
    private String id; 

    @JsonProperty("@class") 
    private String clazz; 

    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    public String getClazz() { 
     return this.getClass().getSimpleName(); 
    } 
} 

而且我的孩子是:

public class Posting extends AbstractBean { 
    private String postingSource; 
    private String languageCode; 

    public String getPostingSource() { 
     return postingSource; 
    } 

    public void setPostingSource(String postingSource) { 
     this.postingSource = postingSource; 
    } 

    public String getLanguageCode() { 
     return languageCode; 
    } 

    public void setLanguageCode(String languageCode) { 
     this.languageCode = languageCode; 
    } 
} 

我不知道爲什麼serailizer甚至會嘗試序列的混入,因爲不是bean的一部分但他們在這裏(是的,我試圖讓它們可序列化,就像測試,沒有運氣一樣):

public interface IdMixins extends Serializable { 
} 

public interface MongoIdMixIn extends IdMixins { 
    @JsonProperty("_id") 
    @JsonSerialize(using = MongoIdSerializer.class) 
    public String getId(); 

    @JsonProperty("_id") 
    @JsonDeserialize(using = MongoIdDeserializer.class) 
    public void setId(String id); 
} 

public class MongoIdDeserializer extends JsonDeserializer<String> implements Serializable { 
    private static final long serialVersionUID = -5404276857799190647L; 

    @Override 
    public String deserialize(JsonParser jp, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { 
     String value = null; 

     String tmp = jp.getText(); // { 
     validate(jp, tmp,"{"); 
     int curly = 1; 

     while (jp.nextToken() != null) { 
      String v = jp.getText(); 

      if (v.equals("{")) curly++; 

      if (v.equals("$oid")) { 
       jp.nextToken(); 
       value = jp.getText(); 
      } 

      if (v.equals("}")) curly--; 
      if (curly<=0) return value; 
     } 

     return null; 
    } 

    private void validate(JsonParser jsonParser, String input, String expected) throws JsonProcessingException { 
     if (!input.equals(expected)) { 
      throw new JsonParseException("Unexpected token: " + input, jsonParser.getTokenLocation()); 
     } 
    } 
} 

public class MongoIdSerializer extends JsonSerializer<String> implements Serializable { 
    private static final long serialVersionUID = 3435689991839324194L; 

    @Override 
    public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { 
     jsonGenerator.writeStartObject(); 
     jsonGenerator.writeFieldName("$oid"); 
     jsonGenerator.writeString(s); 
     jsonGenerator.writeEndObject(); 
    } 
} 
+0

你能提供一個完整的傑克遜樣本嗎?那些mixin是什麼?什麼是'targetClass'? –

+0

@SotiriosDelimanolis目標類只是名稱(config)中的一個類,在這種情況下只是Posting.class。我已將mixin類添加到我的問題 – KIC

回答

1

笨我!序列化鏈中的某個地方是一個完全不必要的ObjectMapper對象。但很難找到,因爲不是Posting對象是真正的原因,而是另一個對象。但Stacktrace和com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer異常完全沒有領先! ...集羣軟件有時真的很難調試:-)

0

我是1 Rep。Point from can be comment。所以我必須提出一個建議作爲答案;-)。

也許其中一個Annotations會將一個TypeWrappedDeserializer實例作爲私有屬性注入到AbstractBean中。也許作爲反序列化機制的暗示。

你可以用反射檢查創建的對象來驗證嗎?

for (Field field : tgtObject.getClass().getDeclaredFields()) 
{ 
    // you can replace this by your logging method 
    System.out.println("Field: " + field.getName() + ":" + field.getType()); 
} 
for (Field field : tgtObject.getClass().getSuperclass().getDeclaredFields()) 
{ 
    // you can replace this by your logging method 
    System.out.println("Field: " + field.getName() + ":" + field.getType()); 
} 

如果您在列表中找到了適當的類型,則類是由字節代碼增強添加的。

+0

我自己嘗試一下。它不起作用。好的,註釋不是責任。但是TypeWrapeDeserializer(這個名字)指出了我的猜測:也許'readerForUpdating(tgtObject)'方法注入了這個Deserializer。但那是我無法檢查的。 –

+0

mixin註解方法也可以提供Annotation影響字節碼。 –

+0

重映射和IDE調試器都不顯示任何有線字段 – KIC