[英]Parsing large JSON file with Scala and JSON4S
我正在使用 IntelliJ IDEA 15 中的 Scala 并尝试解析大型 twitter 记录 json 文件并计算主题标签的总数。 我对 Scala 和函数式编程的想法非常陌生。 json 文件中的每一行都是一个 json 对象(代表一条推文)。 文件中的每一行都是这样开始的:
{"in_reply_to_status_id":null,"text":"To my followers sorry..
{"in_reply_to_status_id":null,"text":"#victory","in_reply_to_screen_name"..
{"in_reply_to_status_id":null,"text":"I'm so full I can't move"..
我对一个名为“entities”的属性最感兴趣,它包含一个名为“hastags”的属性和一个标签列表。 这是一个例子:
"entities":{"hashtags":[{"text":"thewayiseeit","indices":[0,13]}],"user_mentions":[],"urls":[]},
我浏览了用于解析 json 的各种 scala 框架,并决定使用 json4s。 我的 Scala 脚本中有以下代码。
import org.json4s.native.JsonMethods._
var json: String = ""
for (line <- io.Source.fromFile("twitter38.json").getLines) json += line
val data = parse(json)
我的逻辑是我试图将 twitter38.json 中的每一行读入一个字符串,然后用 parse() 解析整个字符串。 parse 函数抛出错误声明:
“类型不匹配,预期:无,找到:字符串。”
我已经看到在包含 json 对象的字符串上使用 parse() 的示例,例如
val jsontest =
"""{
|"name" : "bob",
|"age" : "50",
|"gender" : "male"
|}
""".stripMargin
val data = parse(jsontest)
但我收到了同样的错误。 我来自面向对象的编程背景,我处理这个问题的方式有什么根本错误吗?
您很可能已将对Intellij项目或模块的依赖项错误地导入了文件中。 确保已导入以下行:
import org.json4s.native.JsonMethods._
即使您正确导入了此模块, parse(String: json)
也不适合您,因为您错误地形成了json。 您的json字符串将如下所示:
"""{"in_reply_...":"someValue1"}{"in_reply_...":"someValues2"}"""
但应如下所示,它是可以解析的有效json:
"""{{"in_reply_...":"someValue1"},{"in_reply_...":"someValues2"}}"""
也就是说,您需要json的开头和结尾括号,以及每行tweet之间的逗号。 请阅读json4s文档以获取更多信息。
虽然已经快 6 岁了,但我认为这个问题值得再试一次。
JSON格式在人们的脑海中存在一些误解,尤其是它们的存储方式和回读方式。
JSON 文档存储为具有所有其他字段的单个对象,或者可能以相同格式存储的多个对象的数组。 第二部分很重要,因为几乎每种编程语言中的数组都是由尖括号定义的,值由逗号分隔(注意这里我使用了一个人对象作为我的单个值):
[
{"name":"John","surname":"Doe"},
{"name":"Jane","surname":"Doe"}
]
还要注意,除了括号、数字和布尔值之外的所有内容在写入文件时都用引号引起来。
然而,还有另一种用途不是官方的,但更喜欢轻松传输数据集,其中每个对象或文档(如 nosql/mongo 语言)都存储在新行中,如下所示:
{"name":"John","surname":"Doe"}
{"name":"Jane","surname":"Doe"}
所以对于这个问题,OP 有一个以第二种形式编写的文档,但尝试使用一种算法来读取第一种形式。 以下代码几乎没有简单的更改来实现这一点,用户必须阅读文件知道:
var json: String = "["
for (line <- io.Source.fromFile("twitter38.json").getLines) json += line + ","
json=json.splitAt(json.length()-1)._1
json+= "]"
val data = parse(json)
PS:虽然@sbrannon 的想法是正确的,但他/她给出的示例错误地用大括号而不是尖括号来包围数据。
编辑:我添加了json=json.splitAt(json.length()-1)._1
因为上面的代码以逗号结尾,这将导致每个 JSON 格式定义的解析错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.