如何用部分数据填充json中的case类


import net.liftweb.json._
import net.liftweb.json.JsonParser._
object test02 extends App {
    implicit val formats = DefaultFormats
    case class User(
        id: Int = 0,
        name: String = "John Doe",
        gender: String = "M")
    val s1=""" {"id":1,"name":"Bill","gender":"M"} """
    var r1=Serialization.read[User](s1)
    println(r1)
    val s2=""" {"id":1} """
    var r2=Serialization.read[User](s2)
    println(r2)  
}

第二序列化。net.liftweb.json.MappingException: No usable value for name.

我怎么可能读取数据形式json到case类,但如果一些字段丢失,它们被替换为case类的默认值?

看起来这已经有一段时间了:https://www.assembla.com/spaces/liftweb/tickets/534

同时,一种选择是使用Option:

    case class User(
        id: Int = 0,
        name: Option[String],
        gender: Option[String]) {
      def defaults = copy(
        name   = name   orElse Some("John Doe"),
        gender = gender orElse Some("M"))
    }
    // ...        
    val s2=""" {"id":1} """
    var r2=Serialization.read[User](s2)
    println(r2)  

这应该给你:

 User(1,None,None)

你可以用这样的东西来填充默认值:

 val r2 = Serialization.read[User](s2).defaults
 // r2: User = User(1,Some(John Doe),Some(M))
另一个选择是为case类使用额外的构造函数:
 case class User(id: Int, name: String, gender: String)
 object User {
   def apply(id:Int): User = User(id, "John Doe", "M")
 }

如何使用play json库做到这一点,尽管,您必须在解析器中提供默认值,而不仅仅是默认值:

case class User(id: Int, name: String, gender: String)
import play.api.libs.json._
import play.api.libs.functional.syntax._
implicit val userReads: Reads[User] = (
  (__  "id").read[Int] and
  (__  "name").read[String].or(Reads.pure("John Doe")) and
  (__  "gender").read[String].or(Reads.pure("Male"))
)(User)
Json.fromJson[User](Json.parse("""{"id":1,"name":"Bill","gender":"M"}"""))
Json.fromJson[User](Json.parse("""{"id":1}"""))

我猜你可以通过创建User的模板实例来提供默认参数,然后将每个字段的默认值传递给Reads.pure,而不是在那里硬编码字符串。

这里有一个Play解决方案,它不需要您两次指定默认值或在某些奇怪的地方指定默认值-它使用宏在编译时查找适当的默认值。

第一个case类:

case class User(id: Int = 0, name: String = "John Doe", gender: String = "M")

接下来你需要定义我在这篇博文中描述的DefaultFinder。那么你基本上就完成了:

import DefaultFinder._
import play.api.libs.json._
import play.api.libs.functional.syntax._
implicit val userReads: Reads[User] = (
  (__  'id).readNullable[Int] and
  (__  'name).readNullable[String] and
  (__  'gender).readNullable[String]
)((id, name, gender) => new User(
  id = if (id.isEmpty) default else id.get,
  name = if (name.isEmpty) default else name.get,
  gender = if (gender.isEmpty) default else gender.get
))

最后:

scala> Json.fromJson[User](Json.parse("""{ "id": 1, "name": "Foo McBar" }"""))
res0: play.api.libs.json.JsResult[User] = JsSuccess(User(1,Foo McBar,M),)
scala> Json.fromJson[User](Json.parse("""{ "id": 2, "gender": "X" }"""))
res1: play.api.libs.json.JsResult[User] = JsSuccess(User(2,John Doe,X),)

请注意,我没有使用getOrElse,因为宏不支持它,但它可以很容易地变得更通用——这只是一个快速的概念验证。

大多数scala JSON库都阻塞在这上面。

我们使用内部的JSON库,该库使用宏为丢失的字段提供相同的默认值。(也区分Null为none和Undefined为默认值。所以你可以有一个默认值为Some的选项,如果你想的话)

希望尽快开放源代码。

编辑:基本上,我不知道有其他人这样做。但这是一个不断变化的生态系统,我很好奇是否有人已经解决了这个问题

相关内容

  • 没有找到相关文章