2017-02-19 37 views
-1

我想將com.google.gson.JsonObject轉換爲case類對象。有時在記錄中的一些元素是缺少我希望它被指定爲無,案例類成員Scala條件無值賦值

object tmp { 
    case class person(name: String, age: Long) 
    def main(args: Array[String]): Unit = { 
    val parser = new JsonParser(); 

    //PERSON 2 
    val record2 = parser.parse("""{"name":"xyz"}""").getAsJsonObject() 

    val record2_name = record2.get("name").getAsString.toLowerCase 
    val record2_age = if(record2.get("age") != null) record2.get("age") else None 

    val person2 = new person(record2_name,record2_age) //-> Type Mismatch, expected: Long, actual: Long 

    println(person2); 

    } 
} 

回答

0

在你的情況record2_ageJsonElement型這是一個簡單的Java類型Object的這種情況下,但因爲你是分配None它,它變成Any你試圖分配到Long類型。

簡短的回答是,

val person = new person(jsonObject.get("name").getAsString.toLowerCase, 
    Option(jsonObject.get("age")).map(_.getAsLong).getOrElse(0l)) 

這樣,如果jsonObject.get("age")爲null,Option(null)給你None,或者如果存在的話,你得到Option(28) = Some(28)

你可能想你的年齡是0l如果空。如果你想要它是None,那麼你可以使用Option[Long]

1)簡單的方法

class GsonCaseClassSpecs extends FunSpec { 

    describe("case class conversion") { 

    it("converts gson with name/age to case class") { 

     case class person(name: String, age: Long) 

     val parser = new JsonParser() 

     //case 1 
     val jsonObject : JsonObject = parser.parse("""{"name":"xyz"}""").getAsJsonObject 

     val age = jsonObject.get("age") match { 
     case null => None 
     case value => Some(value.getAsLong) 
     } 

     val person1 = new person(jsonObject.get("name").getAsString.toLowerCase, age.getOrElse(0l)) 

     assert(person1.name == "xyz") 
     assert(person1.age == 0) 

     //case 2 
     val jsonObject2 : JsonObject = parser.parse("""{"name":"xyz", "age" : 28}""").getAsJsonObject 

     val age2 : Option[Long] = jsonObject2.get("age") match { 
     case null => None 
     case value => Some(value.getAsLong) 
     } 

     val person2 = new person(jsonObject2.get("name").getAsString.toLowerCase, age2.getOrElse(0l)) 

     assert(person2.name == "xyz") 
     assert(person2.age == 28) 
    } 

    } 
} 

2)如果你想年齡是Option[Long]Option[T]可以有Some(x)None

class CaseClassFunSpecs extends FunSpec { 

it("converts json to case class with empty age"){ 

    case class person(name: String, age: Option[Long]) 

    val parser = new JsonParser() 

    val json = parser.parse("""{"name":"xyz"}""").getAsJsonObject() 

    val personInstance = new person(json.get("name").getAsString.toLowerCase, 
    Option(json.get("age")).map(_.getAsLong)) 

    assert(personInstance.name == "xyz") 
    assert(personInstance.age == None) 
    // NOTE 
    // do not do personInstance.age.get which would throw 
    // None.get 
    // java.util.NoSuchElementException: None.get 
    // at scala.None$.get(Option.scala:347) 
    // at scala.None$.get(Option.scala:345) 

    //rather use pattern match 
    personInstance.age match { 
    case Some(x) => println("value = " + x) 
    case None => throw new RuntimeException("Age can not be empty.") 
    } 
    } 

it("converts json to case class with non-empty age"){ 

    case class person(name: String, age: Option[Long]) 

    val parser = new JsonParser() 

    val json = parser.parse("""{"name":"xyz", "age" : 28}""").getAsJsonObject() 

    val personInstance = new person(json.get("name").getAsString.toLowerCase, 
    Option(json.get("age")).map(_.getAsLong)) 

    assert(personInstance.name == "xyz") 
    assert(personInstance.age == Some(28)) 
    assert(personInstance.age.get == 28) //.get gives you the value 
} 
} 
+0

這是設置年齡爲0,這可能是。我需要一些東西來表明這個元素從行中丟失。 – xstack2000

+0

@ xstack2000如果是這樣的話,那麼你需要'Option [Long]'。查看更新後的答案。讓我知道這是否有幫助 – prayagupd

+0

@ xstack2000還會在使用'ageOption'時讀取NOTE,因爲'None'上的'.get'將會引發異常,而使用上述的模式匹配。 – prayagupd

1

你根本不能稱之爲一個類型,age: Long的參數在你的情況下,不同類型的Option[Long]的參數。

至少這是你的問題似乎意味着什麼。

您需要定義可能丟失的屬性,如Option s。

例如在你的榜樣

case class person(name: String, age: Option[Long]) 

,然後當你提取JSON值,你可以使用Option.apply方法,返回None如果參數null

… 
val record2_age = Option(record2.get("age")).map(_.getAsLong) // None if get("age) returns null 
… 
val person2 = new person(record2_name,record2_age) //There should be no more type mismatch now 
+0

我嘗試過Option,但它仍然不起作用 val person2 = new person(record2_name,record2_age) // - >類型不匹配,預期:選項[Long],實際:選項[jsonElement] – xstack2000

+0

更新答案,如@ prayagupd的回答,現在就試試 –