2016-09-14 136 views
2

說我有一個映射到傑克遜完整的數據綁定下面的Java對象:NotSerializableException傑克遜ObjectNode

public class Student implements Serializable{ 
    private ObjectNode name; // two keys: "first_name", "last_name" 

    // getter and setter ... 
} 

而且我有試圖序列類型的閉包變量student跟隨星火代碼由於不同的範圍而導致的Student

class A(student : Student) extends Serializable { 
    def process(input: DataFrame): Unit = { 
     val test = input.map { a => 
      print(student) 
     } 
    } 
} 

這給以下錯誤:Caused by: java.io.NotSerializableException: com.fasterxml.jackson.databind.node.ObjectNode

我明白爲什麼我得到這樣的錯誤。基本上,Spark將嘗試序列化所有超出範圍的變量,也就是關閉並將其傳遞給每個執行者。但由於ObjectNode本身不是Serializable,執行者無法獲得Student實例。

我的問題是,我可以解決這個問題的方法是什麼?

我一直在使用Map<String, String>代替ObjectNode試過,但由於ObjectNodeputset只能有‘原始人’和JsonNode的價值,它會導致錯誤,當我嘗試這樣:

ObjectNode meta_info = JsonNodeFactory.instance.objectNode(); 
meta_info.set("field name", student.getName()); 

回答

1

有有幾種選擇。

如果您只需要Object節點用於json序列化目的,那麼您可以重寫您的Student類並完全刪除ObjectNode。在您的例子中,你可以通過對象與firstNamelastName領域

class Name implements Serializable { 
    String firstName; 
    String lastName; 
} 

但是替補多,如果這是不可能的,你可以像這樣

public class Student implements Serializable { 
    private transient ObjectNode name; 

    private void writeObject(ObjectOutputStream out) throws IOException { 
     ObjectMapper mapper = new ObjectMapper(); 
     out.writeUTF(mapper.writeValueAsString(name)); 
     // other fields here 
    } 

    private void readObject(ObjectInputStream in) throws IOException, 
      ClassNotFoundException { 
     ObjectMapper mapper = new ObjectMapper(); 

     JsonNode node = mapper.readTree(in.readUTF()); 
     if (!node.isObject()) { 
      throw new IOException("malformed name field detected"); 
     } 

     name = (ObjectNode) node; 

     // read other fields 
    } 
} 

在我的例子我序列化對象節點做自定義序列json字符串,但你當然可以遍歷對象節點字段分別存儲每個字段。

您可以在ObjectOutputStream javadoc中閱讀更多關於定製序列化的信息。

你也可以嘗試不同的data serializersKryo

0

我最終作出studentMap<String, String>對象,並做mapper.convertValue(student, ObjectNode.class每當我需要它是在ObjectNode