Spark关闭问题中的Jackson ObjectNode的NotSerializableException

时间:2016-09-14 21:43:18

标签: java json scala jackson serializable

假设我有以下Java对象映射到Jackson完整数据绑定:

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

    // getter and setter ...
}

我有一个以下的Spark代码,它试图序列化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将尝试序列化所有超出范围的变量a.k.a. closures并将其传递给每个执行程序。但由于ObjectNode本身不是Serializable,因此执行程序无法获取Student个实例。

我的问题是,我能解决这个问题的方法是什么?

我尝试使用Map<String, String>代替ObjectNode,但由于ObjectNode的{​​{1}}和put只能使用“原语”和{{1}作为值,当我尝试这样的事情时会导致错误:

set

3 个答案:

答案 0 :(得分:2)

有几种选择。

如果您只需要用于json序列化的Object节点,那么您可以重写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 serializers之类的Kryo。{/ p>

答案 1 :(得分:1)

我最终将student发送到Map<String, String>个对象,并且只要我需要它mapper.convertValue(student, ObjectNode.class

ObjectNode

答案 2 :(得分:0)

将jackson-databind升级到10.x有帮助,请参考此https://github.com/FasterXML/jackson-databind/issues/18