【问题标题】:Spark fails to map JSON Integer to Java IntegerSpark 无法将 JSON Integer 映射到 Java Integer
【发布时间】:2019-10-18 15:47:30
【问题描述】:

我有一个定义我的 JSON 的 Java 类,并且这个类包含一些 Integer 属性。 Spark 能够读取此 JSON 并使用上述 Java 类编码器对其进行解析。我还能够执行正常的 Spark SQL 操作。

但是,当我尝试将此 Spark 数据集转换为 JavaRDD 或尝试使用 collectAsList 或 collect 在驱动程序处收集数据时,它会失败并出现编译时错误。

如果我将这些 Integer 属性转换为 Long,一切都会开始工作。
那么,关于“Spark-Java-Integers”,我在这里缺少什么?

像这样的链接只是说明解决方案,而不是说明实际问题的原因。
1) https://issues.apache.org/jira/browse/SPARK-12036
2)Spark CSV - No applicable constructor/method found for actual parameters

以下是我尝试过的代码。它包含 3 个文件。第一个是主要的 Spark 驱动程序代码。第二个是 Person Java 类,它定义了我想要解析和使用的 JSON。第三个文件是 JSON 本身。最后,我还从 pom.xml 中包含了 Spark 依赖项

文件 1:主要的 Spark Java 驱动程序代码

package com.suraj.spark;

import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Encoder;
import org.apache.spark.sql.Encoders;
import org.apache.spark.sql.SparkSession;

import com.suraj.spark.pojos.Person;

public class PersonTest {
    public static void main(String... args) {
        SparkSession spark = SparkSession.builder().master("local").appName("Simple Application")
                .getOrCreate();

        Encoder<Person> pe = Encoders.bean(Person.class);

        Dataset<Person> pdf = spark.read().json("person.json").as(pe);
        pdf.show(); // This works

        JavaRDD<Person> prdd = pdf.toJavaRDD();
        System.out.println(prdd.take(1)); // This fails.
    }
}

文件 2:定义我的 JSON 的人员类

package com.suraj.spark.pojos;

import java.io.Serializable;

public class Person implements Serializable {

    private Integer age;
    private String name;
    private Double height;

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getHeight() {
        return height;
    }

    public void setHeight(Double height) {
        this.height = height;
    }

}

文件 3:包含我的 JSON 字符串的文件。将此保留在项目根目录中。

{"name":"ravi","age":14,"height":6.4}
{"name":null,"age":12,"height":null}

文件 4:我的 pom.xml 的摘录

<dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-sql_2.11</artifactId>
            <version>2.4.4</version>
            <scope>provided</scope>
            <exclusions>
                <exclusion>
                    <groupId>com.google.guava</groupId>
                    <artifactId>guava</artifactId>
                </exclusion>
            </exclusions>
    </dependency>
    <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_2.11</artifactId>
            <version>2.4.4</version>
            <scope>provided</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.curator</groupId>
                    <artifactId>apache-curator</artifactId>
                </exclusion>
            </exclusions>
    </dependency>

预期 = 这应该能够打印 take(1) 方法的输出。
实际结果 = 这是失败并出现以下堆栈的编译时错误

Caused by: java.util.concurrent.ExecutionException: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 57, Column 37: failed to compile: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 57, Column 37: No applicable constructor/method found for actual parameters "long"; candidates are: "public static java.lang.Integer java.lang.Integer.valueOf(int)", "public static java.lang.Integer java.lang.Integer.valueOf(java.lang.String) throws java.lang.NumberFormatException", "public static java.lang.Integer java.lang.Integer.valueOf(java.lang.String, int) throws java.lang.NumberFormatException"

【问题讨论】:

    标签: java apache-spark


    【解决方案1】:

    你得到的不是Integer,而是Long

    No applicable constructor/method found for actual parameters "long";
    

    它试图找到像new Integer(long) 这样的方法来转换它,但没有任何方法,因为它是有损转换。将 Person.age 更改为 Long 即可使用(最简单的选项)。

    【讨论】:

    • 这是否意味着 Spark 在使用将 age 定义为 Integer 的类读取 JSON 时,不尊重它并在内部将其转换为 Long?当我们要求它把它转换为类对象时,它会失败,因为它是有损转换。
    • @surajs21 取决于使用的库和语言,there are no integers or longs。但例如 Jackson 将整数视为 Java Longs。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-04
    • 2019-12-24
    相关资源
    最近更新 更多