【问题标题】:Scala Graph JSON with Play Framework带有 Play 框架的 Scala Graph JSON
【发布时间】:2017-02-03 19:17:02
【问题描述】:

我正在尝试将 POST 请求传递给使用 Play 开发的 REST API! (2.5) 一个我想使用 Scala Graph 的对象(来自 graph-core 依赖项)。 看起来该图已经具有基于 Lift-json 的 JSON 序列化/反序列化方法,但我不确定如何将其“插入”到 Play Json 库中。到目前为止,我一直在使用隐式转换器(使用读/写方法),但我想避免为图形部分编写自己的方法,因为它已经是库本身的一部分。

例如,假设我有这个代码:

import java.util.UUID
import scalax.collection.Graph

case class Task(
  id: UUID,
  status: String)

case class Stuff(
  id: UUID = UUID.randomUUID(),
  name: String,
  tasks: Option[Graph[Task, DiEdge]])

implicit val stuffWrites: Writes[Stuff] = (
    (JsPath \ "id").write[UUID] and
    (JsPath \ "name").write[String]
  )(unlift(Stuff.unapply))

implicit val stuffReads: Reads[Stuff] = (
    (JsPath \ "id").read[UUID] and
    (JsPath \ "name").read[String]
  )(Stuff.apply _)

implicit val taskWrite: Writes[Task] = (
    (JsPath \ "id").write[UUID] and
    (JsPath \ "status").write[String]
  )(unlift(Task.unapply))

implicit val taskReads: Reads[Task] = (
    (JsPath \ "id").read[UUID] and
    (JsPath \ "status").read[String]
  )(Task.apply _)

我错过了序列化图表和育儿的部分。我应该从头开始重写所有内容,还是可以依赖 scalax.collection.io.json 中的 toJson/fromJson 方法?

【问题讨论】:

    标签: json scala playframework-2.0


    【解决方案1】:

    由于我费了一点力气才能让它工作,我想我会分享代码:

    class UUIDSerializer extends Serializer[UUID] {
      private val UUIDClass = classOf[UUID]
    
      def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), UUID] = {
        case (TypeInfo(UUIDClass, _), json) => json match {
          case JString(id) => UUID.fromString(id)
          case x => throw new MappingException("Can't convert " + x + " to UUID")
        }
      }
      def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
        case x: UUID => JString(x.toString)
      }
    }
    
    val extraSerializers = new UUIDSerializer :: Nil
    implicit val formats = Serialization.formats(NoTypeHints) ++ extraSerializers
    
    val taskDescriptor = new NodeDescriptor[Task](typeId = "Tasks", customSerializers=extraSerializers) {
      def id(node: Any) = node match {
        case Task(id, _) => id.toString
      }
    }
    
    val quickJson = new Descriptor[Task](
        defaultNodeDescriptor = taskDescriptor,
        defaultEdgeDescriptor = Di.descriptor[Task]()
    )
    implicit val tasksWrites = new Writes[Graph[Task, DiEdge]] {
      def writes(graph: Graph[Task, DiEdge]): JsValue = {
        val json = graph.toJson(quickJson)
        Json.parse(json.toString)
      }
    }
    
    implicit val tasksReads = new Reads[Graph[Task, DiEdge]] {
      def reads(json: JsValue): JsResult[Graph[Task, DiEdge]] = {
        try {
          val graph = Graph.fromJson[Task, DiEdge](json.toString, quickJson)
          JsSuccess(graph)
        }
        catch {
          case e: Exception =>
            JsError(e.toString)
        }
      }
    }
    
    implicit def stuffModelFormat = Jsonx.formatCaseClass[Stuff]
    

    【讨论】:

      【解决方案2】:

      您可以尝试为您指定格式的案例类编写伴随对象。

      例子:

      object Task {
        implicit val taskModelFormat = Json.format[Task]
      }
      
      object Stuff {
        implicit val staffModelFormat = Json.format[Stuff]
      }
      

      而不是上面的implicits。使用此解决方案,编译器将为您解析已知的格式化程序,您可能只需要指定丢失/未知的类型而不是整个结构。

      【讨论】:

      • 谢谢!事实上,当我昨天重新阅读 Play 文档时,我看到了这一点。但我仍然怀念如何处理 Scala Graph 的部分:-)。
      • 好吧,您可以为缺少的类型编写隐式函数,并在这些类中返回用 Lift... 解析的 String... 或完全切换到 Lift。否则,您将不得不查找/编写新的解析器。
      • 不幸的是,我正在努力做到这一点。如果我设法有一些有用的东西,我会在这里发布一些东西。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-11
      • 2011-12-05
      • 1970-01-01
      • 2013-05-28
      • 1970-01-01
      相关资源
      最近更新 更多