使用Json.format函数后如何从缺少字段的客户端为其相应的Case类发送Json [英] How to send Json from client with missing fields for its corresponding Case Class after using Json.format function

查看:92
本文介绍了使用Json.format函数后如何从缺少字段的客户端为其相应的Case类发送Json的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个case类及其配套对象,如下所示.现在,当我发送不带id,createdAt和DeletedAt字段的JSON时,因为在其他地方设置了它们,所以出现[NoSuchElementException: JsError.get]错误.这是因为我没有设置以上属性.

I have a case Class and its companion object like below. Now, when I send JSON without id, createdAt and deletedAt fields, because I set them elsewhere, I get [NoSuchElementException: JsError.get] error. It's because I do not set above properties.

我该如何做到这一点并避免出错?

How could I achieve this and avoid getting the error?

case class Plan(id: String,
                companyId: String,
                name: String,
                status: Boolean = true,
                @EnumAs planType: PlanType.Value,
                brochureId: Option[UUID],
                lifePolicy: Seq[LifePolicy] = Nil,
                createdAt: DateTime,
                updatedAt: DateTime,
                deletedAt: Option[DateTime]
                )

object Plan {
   implicit val planFormat = Json.format[Plan]
   def fromJson(str: JsValue): Plan = Json.fromJson[Plan](str).get
   def toJson(plan: Plan): JsValue = Json.toJson(plan)
   def toJsonSeq(plan: Seq[Plan]): JsValue = Json.toJson(plan)
}

我从客户端发送的JSON

JSON I send from client

{
    "companyId": "e8c67345-7f59-466d-a958-7c722ad0dcb7",
    "name": "Creating First Plan with enum Content",
    "status": true,
    "planType": "Health",
    "lifePolicy": []
}

推荐答案

基本问题是,在实例化case class表示您的数据时,必须对其进行正确键入.为了将示例数据插入示例类,类型不匹配,因为缺少某些字段.从字面上看,它试图在没有足够参数的情况下调用构造函数.

The fundamental issue is that by the time a case class is instantiated to represent your data, it must be well-typed. To shoe horn your example data into your example class, the types don't match because some fields are missing. It's literally trying to call the constructor without enough arguments.

您有两种选择:

  • 您可以创建一个表示不完整数据的模型(如grotrianster建议).
  • 您可以将可能缺少的字段设为Option类型.
  • 您可以自定义编写FormatReads部分,以为丢失的值引入智能值或伪值.
  • You can make a model that represents the incomplete data (as grotrianster suggested).
  • You can make the possible missing fields Option types.
  • You can custom-write the Reads part of your Format to introduce intelligent values or dummy values for the missing ones.

选项3可能类似于:

// Untested for compilation, might need some corrections

val now: DateTime = ...

val autoId = Reads[JsObject] { 
  case obj: JsObject => JsSuccess(obj \ 'id match {
    case JsString(_) => obj
    case _ => obj.transform(
      __.update((__ \ 'id).json.put("")) andThen
      __.update((__ \ 'createdTime).json.put(now)) andThen
      __.update((__ \ 'updatedTime).json.put(now))
    )
  })
  case _ => JsError("JsObject expected")
}

implicit val planFormat = Format[Plan](
  autoId andThen Json.reads[Plan],
  Json.writes[Plan])

一旦执行一次,如果所有其他模型的问题都相同,则可以将其抽象为某些Format工厂实用程序函数.

Once you do this once, if the issue is the same for all your other models, you can probably abstract it into some Format factory utility function.

对于autoId,这可能更干净:

val autoId = Reads[JsObject] {
  // Leave it alone if we have an ID already
  case obj: JsObject if (obj \ 'id).asOpt[String].isSome => JsSuccess(obj)
  // Insert dummy values if we don't have an `id`
  case obj: JsObject => JsSuccess(obj.transform(
    __.update((__ \ 'id).json.put("")) andThen
    __.update((__ \ 'createdTime).json.put(now)) andThen
    __.update((__ \ 'updatedTime).json.put(now))
  ))
  case _ => JsError("JsObject expected")
}

这篇关于使用Json.format函数后如何从缺少字段的客户端为其相应的Case类发送Json的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆