2017-08-04 29 views
1

大家最近我遇到了一個問題,將json轉換成我自己的數據模型。玩框架json從空字符串讀取到空列表

我有可能包含一個空字符串一個JSON格式的消息:

{ 
    "name" : "John Doe", 
    "hobbies": "" 
} 

或愛好類型的列表:

{ 
    "name" : "John Doe", 
    "hobbies": [{"name":"basketball"}] 
} 

而下面是Scala發揮我的案例類的數據模型框架:

case class Person(name: String, hobbies: List[Hobby]) 
case class Hobby(name: String) 

現在我使用默認的json格式化程序,但它當然是當我們將空字符串作爲值時,效果不佳。

implicit val HobbyJson= Json.format[Hobby] 
implicit val PersonJson = Json.format[Person] 

如果hobbies有一個空字符串,它會拋出異常。當它是空字符串時,我想將它轉換爲空列表。我搜索Play提供的文檔,但找不到信息。任何人都可以提一些建議嗎

在此先感謝。

回答

0

正如您所提到的,由於hobbies的處理方法不一致,所以在此處默認的Format宏將不適用於您。所以,你需要實現自己的Reads[Person] - 這裏就是我會做它:

object PersonJson { 
    implicit val hobbyConverter = Json.format[Hobby] 

    val personReads = new Reads[Person] { 

    override def reads(json: JsValue): JsResult[Person] = { 
     for { 
     personName <- (json \ "name").validate[String] 
     hobbies  <- (json \ "hobbies").validate[JsValue] 
     } yield { 
     val maybeHobbyList = hobbies.validate[List[Hobby]].asOpt 
     Person(personName, maybeHobbyList.getOrElse(Nil)) 
     } 
    } 
    } 

    implicit val personConverter = Format(personReads, Json.writes[Person]) 
} 

關鍵的一點要注意的是這裏周圍的JsResult禮貌的,理解和yield整個事情。這給我們所有必要的檢查(如name字段在那裏,是一個字符串,並且hobbies字段在那裏)。

yield塊中的代碼僅在我們看到非常接近Person的東西時纔會運行。然後我們可以安全地嘗試驗證hobbiesList[Hobby],並將結果轉換爲Option[List[Hobby]]。如果它不起作用,它將是一個None(因此它必須是一個字符串),所以我們根據需要將它默認爲空列表。

0

謝謝@millhouse答案,它絕對有效。就像他說我們需要一個自定義Reads[Person]來正確轉換它。

我也發佈我的代碼作爲參考。

implicit val personJsonReads: Reads[Person] = (
     (__ \ "name").read[String] and 
     (__ \ "hobbies").read[List[Hobby]].orElse(Reads.pure(List())) 
) (Person.apply _) 

read[List[Hobby]].orElse(Reads.pure(List()))會產生空列表時,值不能轉換爲List[Hobby]