bigdecimal setscale在spark udf中不起作用

fnatzsnv  于 2021-05-27  发布在  Spark
关注(0)|答案(1)|浏览(420)

我试图将json列转换为map。我尝试用udf将json转换成map。但它并没有像预期的那样起作用。

val df1 = Seq(("{\"k\":10.004}")).toDF("json")
def udfJsonStrToMapDecimal = udf((jsonStr: String)=> { var jsonMap:Map[String,Any] = parse(jsonStr).values.asInstanceOf[Map[String, Any]]
     jsonMap.map{case(k,v) => (k,BigDecimal.decimal(v.asInstanceOf[Double]).setScale(6))}.toMap
})
val f = df1.withColumn("map",udfJsonStrToMapDecimal($"json"))
scala> f.printSchema
root
 |-- json: string (nullable = true)
 |-- map: map (nullable = true)
 |    |-- key: string
 |    |-- value: decimal(38,18) (valueContainsNull = true)

这里需要帮助,而不是十进制(38,6)将值转换为十进制(38,18)

8xiog9wr

8xiog9wr1#

默认的十进制进位是 DecimalType(38, 18) ,我不知道你想做什么,但是
可以将当前十进制类型转换为

df1.withColumn("map",udfJsonStrToMapDecimal($"json").cast("map<string, decimal(38,6)>"))

架构:

root
 |-- json: string (nullable = true)
 |-- map: map (nullable = true)
 |    |-- key: string
 |    |-- value: decimal(38,6) (valueContainsNull = true)

或者您也可以定义模式并直接作为json读取

val schema = StructType(StructField("k", DecimalType(38, 6), nullable = false) :: Nil)

val df1 = Seq(("{\"k\":10.004}")).toDF("json")

val result = df1.withColumn("value", from_json($"json", schema))

架构:

root
 |-- json: string (nullable = true)
 |-- value: struct (nullable = true)
 |    |-- k: decimal(38,6) (nullable = true)

相关问题