我有很少的json消息,比如
{"column1":"abc","column2":"123","column3":qwe"r"ty,"column4":"abc123"}
{"column1":"defhj","column2":"45","column3":asd"f"gh,"column4":"def12d"}
我需要为column3值添加双引号,并使用scala将column3值中的双引号替换为单引号。
答案 0 :(得分:0)
您在上面的评论中提到了
我在kafka中有大量的数据集。我正在尝试从kafka读取并使用scala通过spark写入hdfs。我正在使用json解析器但由于column3问题而无法解析。因此需要操纵消息以更改为json
所以你必须像问题一样收集畸形的jsons。我创建了一个列表
val kafkaMsg = List("""{"column1":"abc","column2":"123","column3":qwe"r"ty,"column4":"abc123"}""", """{"column1":"defhj","column2":"45","column3":asd"f"gh,"column4":"def12d"}""")
你正在通过Spark阅读它,所以你必须将rdds作为
val rdd = sc.parallelize(kafkaMsg)
所有你需要的是在格式错误的文本json中进行一些解析,使其成为有效的json字符串
val validJson = rdd.map(msg => msg.replaceAll("[}\"{]", "").split(",").map(_.split(":").mkString("\"", "\":\"", "\"")).mkString("{", ",", "}"))
validJson
应该是
{"column1":"abc","column2":"123","column3":"qwerty","column4":"abc123"}
{"column1":"defhj","column2":"45","column3":"asdfgh","column4":"def12d"}
你可以从validJson rdd 创建一个数据框作为
sqlContext.read.json(validJson).show(false)
应该给你
+-------+-------+-------+-------+
|column1|column2|column3|column4|
+-------+-------+-------+-------+
|abc |123 |qwerty |abc123 |
|defhj |45 |asdfgh |def12d |
+-------+-------+-------+-------+
或者你可以按照你的要求去做。
答案 1 :(得分:0)
<强>目标强>
为column3值添加双引号,并使用scala将column3值中的双引号替换为单引号。
我建议使用RegEx,因为你可以更灵活地使用它。
以下是解决方案:
val kafkaMsg = List("""{"column1":"abc","column2":"123","column3":qwe"r"ty,"column4":"abc123"}""", """{"column1":"defhj","column2":"45","column3":asd"f"gh,"column4":"def12d"}""", """{"column1":"defhj","column2":"45","column3":without-quotes,"column4":"def12d"}""")
val rdd = sc.parallelize(kafkaMsg)
val rePattern = """(^\{.*)("column3":)(.*)(,"column4":.*)""".r
val newRdd = rdd.map(r =>
r match {
case rePattern(start, col3, col3Value, end) => (start + col3 + '"' + col3Value.replaceAll("\"", "'") + '"' + end)
case _ => r }
)
newRdd.foreach(println)
<强>解释强>
第一个和第二个语句是rdd初始化。
第三行定义正则表达式模式。您可能需要根据自己的情况进行调整。
正则表达式产生4组值(a()中的任何值都是一组):
我在下一个声明中使用这4组。
迭代你的rdd,对正则表达式运行它,并更改它:用单引号替换双引号,并添加打开/关闭引号。如果没有匹配,将返回原始字符串。
因为regex是用4组定义的,所以我使用4个变量来映射匹配:
case rePattern(start, col3, col3Value, end) =>
注意:代码不会检查您是否在值中有双引号,它只是运行更新。如果需要,您可以自己添加验证。
显示结果。
重要说明: 我使用的正则表达式严格链接到您的源字符串格式。请记住,您有JSON,因此无法保证您的密钥顺序。因此,最终可能会出现“column4”(用作column3值结尾)可能会出现在“column3”之前。
如果您使用逗号作为键/值结尾,请确保您没有将其作为column3值的一部分。
底线:您需要调整我的正则表达式以正确识别column3值的结尾。
希望它有所帮助。