2016-01-26 18 views
0

我有一個聯繫人類,
它將(JsPath \ "contact_name" \ "first_name")改爲firstName,但(JsPath \ "contact_name")可以爲空。
有沒有人知道如何做這個案例類的讀者?PlayJson Scala讀取可空字段

case class Contact(var firstName: Option[String], 
        var lastName: Option[String]) 

而我接觸Json是:

{ 
    "contact_name": { 
    "first_name": "hello", 
    "last_name": "world" 
    }, 
    "phone_number": "1231231234", 
    "email": "[email protected]" 
} 

聯繫Json無 「CONTACT_NAME」:

{ 
    "phone_number": "1231231234", 
    "email": "[email protected]" 
} 

我想這兩個Json能夠閱讀到聯繫對象。謝謝。

回答

1

假設你的電話號碼和電子郵件是的聯繫方式部分,這裏有一個工程(你可以用\\搜索深度路徑):

import play.api.libs.json._ 
import play.api.libs.functional.syntax._ 

case class Contact(firstName: Option[String], lastName: Option[String], 
        phone: String, email: String) 

val contactReads: Reads[Contact] = (
    (__ \\ "first_name").readNullable[String] and 
    (__ \\ "last_name").readNullable[String] and 
    (__ \ "phone_number").read[String] and 
    (__ \ "email").read[String] 
)(Contact.apply _) 

val json1 = """{ 
    | "contact_name": { 
    | "first_name": "hello", 
    | "last_name": "world" 
    | }, 
    | "phone_number": "1231231234", 
    | "email": "[email protected]" 
    |}""".stripMargin 

Json.parse(json1).validate[Contact](contactReads) 
// JsSuccess(Contact(Some(hello),Some(world),1231231234,[email protected]),) 

val json2 = """{ 
    | "phone_number": "1231231234", 
    | "email": "[email protected]" 
    |}""".stripMargin 

Json.parse(json2).validate[Contact](contactReads) 
// JsSuccess(Contact(None,None,1231231234,[email protected]),) 
0

我沒有寫上一個帖子 - http://pedrorijo.com/blog/scala-json/

它接近如何讀取JSON到案例類。具體來說,讀可選字段從JSON,在最後一個例子:

case class User(username: String, friends: Int, enemies: Int, isAlive: Option[Boolean]) 

object User { 

    import play.api.libs.functional.syntax._ 
    import play.api.libs.json._ 

    implicit val userReads: Reads[User] = (
     (JsPath \ "username").read[String] and 
     (JsPath \ "friends").read[Int] and 
     (JsPath \ "enemies").read[Int] and 
     (JsPath \ "is_alive").readNullable[Boolean] 
    ) (User.apply _) 
} 

應該足夠你完成它。 另外,如果json與所需的字段的字符串,你可以這樣寫:

Json.parse(json) 

所以,如果fullJson是完整的JSON對象(與那些不需要的字段),你可以只提取名字和姓氏與fullJson \ "contact_name"

0

爲了簡化事情我已經做了這樣的事情(儘管它創造了很多班):

假設:CONTACT_NAME是可選的,要摺疊整個事情到一個單一的情況下,類Contact

{ 
    "contact_name": { 
    "first_name": "hello", 
    "last_name": "world" 
    }, 
    "phone_number": "1231231234", 
    "email": "[email protected]" 
} 


case class Contact(firstName: Optional[String], lastName: Optional[String], phoneNumber: String, email: String) 

case class RawContactName(firstName: String, lastName: String) 
case class RawContact(contactName: Optional[RawContactName], phoneNumber: String, email: String) 

implicit val rawContactReads: Reads[RawContact] = (
     (JsPath \ "contact_name").readNullable[RawContactName] and 
     (JsPath \ "phone_number").read[String] and 
     (JsPath \ "email").read[String] 
    ) (RawContact.apply _) 

implicit val rawContactNameReads: Reads[RawContactName] = (
     (JsPath \ "first_name").read[String] and 
     (JsPath \ "last_name").read[String] 
    ) (RawContactName.apply _) 

def transformContact(rawContact: RawContact): Contact = { 
    val (maybeFirstName, maybeLastName) = rawContact.contactName match { 
     case Some(RawContactName(firstName, lastName)) => (Some(firstName), Some(lastName)) 
     case None => (None, None) 
    } 
    Contact(maybeFirstName, maybeLastName, rawContact.phoneNumber, rawContact.email) 
} 

有效地,我有單獨的情況下的類來表示每個節點JSON和變壓器函數來Scala的JSON表示變換爲我的模型類。如果你有重複的值,這是有效的(例如:在同一個JSON文檔中有多個聯繫對象,所以會出現多個first_name元素)。雖然在你的具體例子中,最好跳過Raw類並在模型中創建兩個case類:ContactContactName,但我想演示一個將View模型(Raw...)與內部模型分開的通用解決方案。

相關問題