【问题标题】:Parse Json List with 1 element (Scala/liftweb)使用 1 个元素解析 Json 列表(Scala/liftweb)
【发布时间】:2012-09-28 13:16:15
【问题描述】:

我遇到了从外部服务器检索一些 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 类定义如下,则第二个解析将起作用,但第一个解析将失败。

    case class JSonListIssue(foo: String)

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

谢谢, 格罗

【问题讨论】:

  • 仅供参考,您可以在 scala 中使用三引号字符串。这样一来,jsonStr2Foos = """{"foo": "bar", "foo": "bar2"}""" 就不必转义所有这些引号。
  • 如果你改为尝试:case class FooBar (foo:String, bar:String),然后:val json = parse(jsonStrFoo).extract(List[FooBar]) ?
  • 没关系,这行不通。我读错了你的输入。

标签: json scala lift lift-json


【解决方案1】:

因此,首先,虽然您无法控制编写该 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])
  }
}

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

如果这不起作用,请告诉我。如果有什么更清洁的事情发生在我身上,我会告诉你的。干杯,伙计!

【讨论】:

    猜你喜欢
    • 2016-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多