2017-02-19 87 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的回答,现在就试试 –