如何在Scala中使用JSON.parseFull时报告解析错误
当我的应用程序接收到语法不正确的JSON时,我希望能够向用户报告错误,并提供一些有用的细节,以便找到问题区域 因此,在本例中,j将是None,因为“File1”后面有一个逗号。是否有方法获取上次分析错误的详细信息如何在Scala中使用JSON.parseFull时报告解析错误,json,scala,Json,Scala,当我的应用程序接收到语法不正确的JSON时,我希望能够向用户报告错误,并提供一些有用的细节,以便找到问题区域 因此,在本例中,j将是None,因为“File1”后面有一个逗号。是否有方法获取上次分析错误的详细信息 val badSyntax = """ { "menu1": { "id": "file1", "value": "File1", }, "menu2": { "id": "file2", "value": "File2", }
val badSyntax = """
{
"menu1": {
"id": "file1",
"value": "File1",
},
"menu2": {
"id": "file2",
"value": "File2",
}
}"""
val j = JSON.parseFull(badSyntax)
当出现解析错误时,使用
JSON.lastnosucces
获取最后一个错误。它属于JSON.NoSuccess
类型,其中有两个子类,JSON.Error
和JSON.Failure
,都包含详细说明错误的msg:String
成员。
请注意,JSON.lastNoSuccess
不是线程安全的(它只是一个全局变量),现在已被弃用(必然会在scala 2.11中消失)
更新:显然,我错误地认为它不是线程安全的:在scala 2.10之前它确实不是线程安全的,但是现在lastNoSuccess
由线程局部变量支持(因此在多线程上下文中使用是安全的)。
在完成此任务后,您可以认为,只要您在解析失败后立即阅读与用于解析的线程相同的线程(您称之为parseFull
)中的,那么一切都将按预期工作。不幸的是,在此重构过程中,他们还改变了lastNoSuccess
在Parsers.phrase
内部使用JSON.parseFull
的方式。
看见
由于此重构,lastnosucces
在Parsers.phrase
的末尾被重置为None
。这在解析器中通常没有问题,因为lastNoSuccess
被用作作为解析器的结果返回的临时值。
这里的问题是,我们不调用Parsers.phrase
,而是调用JSON.parseFull
,这会删除任何错误信息(请参见case None=>None
方法内的JSON.parseRaw
at)。
在scala 2.10之前,JSON.parseFull
删除任何错误信息的事实可以通过直接读取JSON.lastNoSuccess
轻松避免,正如我之前所建议的,但是现在在Parsers.phrase
的末尾重置了该值,因此您无法从JSON
中获取错误信息
有解决方案吗?有。您可以创建自己的JSON
版本,该版本不会删除错误信息:
import util.parsing.json._
object MyJSON extends Parser {
def parseRaw(input : String) : Either[NoSuccess, JSONType] = {
phrase(root)(new lexical.Scanner(input)) match {
case Success(result, _) => Right(result)
case ns: NoSuccess => Left(ns)
}
}
def parseFull(input: String): Either[NoSuccess, Any] = {
parseRaw(input).right.map(resolveType)
}
def resolveType(input: Any): Any = input match {
case JSONObject(data) => data.transform {
case (k,v) => resolveType(v)
}
case JSONArray(data) => data.map(resolveType)
case x => x
}
}
我刚刚将选项
更改为或
作为结果类型,这样我就可以将解析错误作为左
返回
scala> MyJSON.parseFull("[1,2,3]")
res11: Either[MyJSON.NoSuccess,Any] = Right(List(1.0, 2.0, 3.0))
scala> MyJSON.parseFull("[1,2,3")
res12: Either[MyJSON.NoSuccess,Any] =
Left([1.7] failure: end of input
[1,2,3
^)
感谢您的回答,但它不适用于我的2.10.0版本。JSON。lastNoSuccess
在解析错误数据后为null
。事实上,我现在可以确认这一点。我进行了(长时间)更新,请查看。