5

我遇到了从外部服务器检索一些 Json 的情况(我对该服务器没有任何控制权)。Json 有一个元素可能出现 1 次或多次。我正在尝试使用 net.liftweb.json 工具对其进行解析,并且仅当元素出现不止一次时才能正常工作。如果元素只出现一次,则解析失败。

这是一些示例代码:

import net.liftweb.json._
import net.liftweb.json.JsonDSL._

case class JSonListIssue(foo: List[String])

class JSonTest extends TestCase {

  implicit val formats = net.liftweb.json.DefaultFormats; 

  def testJsonList {
    val jsonStr2Foos = "{\"foo\": \"bar\", \"foo\": \"bar2\"}"
    val json = (parse(jsonStr2Foos).extract[JSonListIssue]) 
    assertEquals(2, json.foo.size)

    val jsonStr1Foo = "{\"foo\": \"bar\"}"
    val json2 = (parse(jsonStr1Foo).extract[JSonListIssue]) // Results in Json MappingException
    assertEquals(1, json2.foo.size)
  }

}

上述代码中的第二个 parse 语句失败。如果我按如下方式定义案例类,则第二个解析将起作用,但第一个解析将失败。

    case class JSonListIssue(foo: String)

关于如何以干净的方式解决这个问题的任何建议?我当然可以捕获 MappingException 然后使用另一个案例类对其进行解析,但是那很脏......

谢谢,格罗

4

1 回答 1

0

因此,首先,虽然您无法控制编写该 API 的人,但如果您遇到他们,请不要因为他们做了这么愚蠢的事情而对他们开枪。:P

所以,这不是世界上最干净的解决方案,但我想我想出了一些对你有用的东西。可以直接查询使用\运算符解析JSON产生的JValue。

所以,这样的事情应该适合你。

case class JsonListIssue(foo: List[String])

def extractJsonListIssue(json: JValue) = {
  json \ "foo" match {
    case JString(foo) =>
      JsonListIssue(List(foo))

    case _ =>
      json.extract[JsonListIssue]
  }
}

你可能需要也可能不需要括号json \ "foo"来编译。但!我认为这在大多数情况下对你有用。FWIW,如果你想成为真正的 Lift-y,你应该认真考虑在这里使用 Box 并使用 tryo 将提取的任何异常转换为可以在调用堆栈中更高位置的失败。所以,这看起来像这样:

// Add these guys to your existing imports
import net.liftweb._
  import common._
  import util.Helpers._

case class JsonListIssue(foo: List[String])

def extractJsonListIssue(json: JValue) = {
  json \ "foo" match {
    case JString(foo) =>
      Full(JsonListIssue(List(foo)))

    case _ =>
      // Will return a Full with the result of the method on
      // success and a Failure if extract throws an exception.
      tryo(json.extract[JsonListIssue])
  }
}

然后,您可以在代码的其他地方使用它来理解。

如果这不起作用,请告诉我。如果我有什么更清洁的事情,我会告诉你的。队友的欢呼声!

于 2012-10-01T03:16:19.687 回答