gpt4 book ai didi

scala - 使用 Casbah/Salat 定义自定义序列化 - 或者将序列化委托(delegate)给成员?

转载 作者:可可西里 更新时间:2023-11-01 09:32:21 28 4
gpt4 key购买 nike

我正在为一个来自 Rails 的新项目学习 Scala。我已经定义了一个将在我的许多模型中使用的类型,它基本上可以被认为是“属性”的集合。它基本上只是一个 hashmap 的包装器,将其大部分职责委托(delegate)给它:

case class Description(attributes: Map[String, String]) {

override def hashCode: Int = attributes.hashCode

override def equals(other: Any) = other match {
case that: Description => this.attributes == that.attributes
case _ => false
}
}

然后我会用Description定义一个模型类,比如:

case class Person(val name: String, val description: Description)

但是,当我将 Person 与 SalatDAO 持久化时,我最终得到的文档如下所示:

{
name : "Russell",
description:
{
attributes:
{
hair: "brown",
favourite_color: "blue"
}
}
}

实际上我不需要在 description 标签中嵌套 attributes 标签——我真正想要的是:

{
name : "Russell",
description:
{
hair: "brown",
favourite_color: "blue"
}
}

我没试过,但我想如果我让 Description 扩展一个 Map 而不是包含一个,我想我可以让它工作,但我宁愿不,因为 Description 不是 Map 的一种,它具有 Map 的某些行为以及它自己的我稍后会添加。组合优于继承等等。

所以我的问题是,我如何告诉 Salat(或 Casbah,实际上我有点不清楚是哪个在进行转换,因为我才刚刚开始使用它们)如何序列化和反序列化 说明类?在casbah教程中here它说:

It is also possible to create your own custom type serializers and deserializers. See Custom Serializers and Deserializers.

但是这个页面好像不存在。还是我走错了路?实际上是否有一种非常简单的方法来表明这是我想要发生的事情,注释或其他什么?或者我可以简单地将序列化以某种方式委托(delegate)给属性映射吗?

编辑:在查看了 JodaTime 转换助手的源代码后,我尝试了以下方法,但还没有成功:

import org.bson.{ BSON, Transformer }
import com.mongodb.casbah.commons.conversions.MongoConversionHelper

object RegisterCustomConversionHelpers extends Serializers
with Deserializers {
def apply() = {
super.register()
}
}

trait Serializers extends MongoConversionHelper
with DescriptionSerializer {

override def register() = {
super.register()
}
override def unregister() = {
super.unregister()
}
}

trait Deserializers extends MongoConversionHelper {
override def register() = {
super.register()
}
override def unregister() = {
super.unregister()
}
}

trait DescriptionSerializer extends MongoConversionHelper {
private val transformer = new Transformer {
def transform(o: AnyRef): AnyRef = o match {
case d: Description => d.attributes.asInstanceOf[AnyRef]
case _ => o
}
}

override def register() = {
BSON.addEncodingHook(classOf[Description], transformer)
super.register()
}
}

当我调用 RegisterCustomConversionHelpers() 然后保存一个 Person 时,我没有收到任何错误,它只是没有效果,保存文档的方式与以往相同。为了我想要的,这似乎还有很多事情要做。

最佳答案

Salat 维护者在这里。

我不明白 Description 在这里作为包装器的值(value)。它包装了一个属性映射,覆盖了一个 case 类的默认 equals 和 hashcode impl——这似乎是不必要的,因为无论如何 impl 被委托(delegate)给了映射,而这正是 case 类所做的——并引入了一个额外的间接层序列化对象。

您是否考虑过:

case class Person(val name: String, val description: Map[String, String])

这将完全满足您的需求。

在另一种情况下,我会推荐一个简单的类型别名,但不幸的是,Salat 目前无法支持类型别名,因为它们在 pickled Scala 签名中的描述方式存在一些问题。

(您可能出于简洁的考虑从您的示例中省略了这一点,但是您的 Mongo 模型最好有一个 _id 字段 - 如果您没有,Mongo Java 驱动程序将为您提供一个)

salat-core 测试包中有一个自定义 BSON Hook 的工作示例(它处理 java.net.URL)。可能是因为您没有在正确的位置注册它,所以您的钩子(Hook)无法正常工作?但是,我仍然建议去掉 Description,除非它添加了一些在上面的示例中不明显的值。

关于scala - 使用 Casbah/Salat 定义自定义序列化 - 或者将序列化委托(delegate)给成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9531846/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com