没有 play.api.libs.json.Format 的实例可用于 akka.actor.typed.ActorRef[org.knoldus.eventSourcing.UserState.Confirmation]

No instance of play.api.libs.json.Format is available for akka.actor.typed.ActorRef[org.knoldus.eventSourcing.UserState.Confirmation]

No instance of play.api.libs.json.Format is available for akka.actor.typed.ActorRef[org.knoldus.eventSourcing.UserState.Confirmation] in the implicit scope (Hint: if declared in the same file, make sure it's declared before)

[error] implicit val userCommand: Format[AddUserCommand] = Json.format

即使我为 AddUserCommand.

创建了 Json Format 的隐式实例,我仍然收到此错误

这是我的代码:

trait UserCommand extends CommandSerializable
    
object AddUserCommand{
  implicit val format: Format[AddUserCommand] = Json.format[AddUserCommand]
}
    
final case class AddUserCommand(user:User, reply: ActorRef[Confirmation]) extends UserCommand

谁能帮我解决这个错误以及如何解决它?

错误说它无法为 AddUserCommand 构造一个 Format 因为 ActorRef[Confirmation] 没有 Format

使用 Json.format[X] 时,案例 class X 的所有成员都必须定义 Format

在您的情况下,您可能不想为这种情况定义格式化程序 class(序列化 ActorRef 没有多大意义)而是构建另一种情况 class 只有数据。

编辑:如果您真的想向那里发送演员参考,请参阅 Levi 关于如何为 ActorRef 提供格式化程序的回答。

正如 Gael 指出的那样,您需要为 ActorRef[Confirmation] 提供 Format。复杂的是,使用 the ActorRefResolver 的自然序列化要求存在 ExtendedActorSystem,这意味着在伴随对象中定义 Format 的通常方法将无法正常工作.

请注意,由于 Lagom 进行依赖注入的方式,this approach doesn't really work in Lagom: commands in Lagom basically can't use Play JSON

import akka.actor.typed.scaladsl.adapter.ClassicActorSystemOps
import play.api.libs.json._

class PlayJsonActorRefFormat(system: ExtendedActorSystem) {
  def reads[A] = new Reads[ActorRef[A]] {
    def reads(jsv: JsValue): JsResult[ActorRef[A]] =
      jsv match {
        case JsString(s) => JsSuccess(ActorRefResolver(system.toTyped).resolveActorRef(s))
        case _ => JsError(Seq(JsPath() -> Seq(JsonValidationError(Seq("ActorRefs are strings"))))) // hopefully parenthesized that right...
      }
  }

  def writes[A] = new Writes[ActorRef[A]] {
    def writes(a: ActorRef[A]): JsValue = JsString(ActorRefResolver(system.toTyped).toSerializationFormat(a))
  }

  def format[A] = Format[ActorRef[A]](reads, writes)
}

然后您可以将 AddUserCommand 的格式定义为

object AddUserCommand {
  def format(arf: PlayJsonActorRefFormat): Format[AddUserCommand] = {
    implicit def arfmt[A]: Format[ActorRef[A]] = arf.format

    Json.format[AddUserCommand]
  }
}

因为你可能使用 JSON 来序列化围绕集群发送的消息(否则,ActorRef 不应该像这样泄漏),你将构造一个实例Akka Serializer 实现中的格式。

(注意:我只用 Circe 做过这个,没有用 Play JSON,但基本方法很常见)