使用Json.format函数后如何从缺少字段的客户端为其相应的Case类发送Json [英] How to send Json from client with missing fields for its corresponding Case Class after using Json.format function
问题描述
我有一个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
类型. - 您可以自定义编写
Format
的Reads
部分,以为丢失的值引入智能值或伪值.
- 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 yourFormat
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屋!