我需要序列化/反序列化具有如下结构的 Scala 类:
@JsonIgnoreProperties(ignoreUnknown = true, value = Array("body"))
case class Example(body: Array[Byte]) {
lazy val isNativeText = bodyIsNativeText
lazy val textEncodedBody = (if (isNativeText) new String(body, "UTF-8") else Base64.encode(body))
def this(isNativeText: Boolean, textEncodedBody: String) = this((if(isNativeText) str.getBytes("UTF-8") else Base64.decode(textEncodedBody)))
def bodyIsNativeText: Boolean = // determine if the body was natively a string or not
}
它的主要成员是一个字节数组,它可能代表一个 UTF-8 编码的文本字符串,但可能不是。主构造函数接受一个字节数组,但还有一个替代构造函数接受一个带有标志的字符串,该标志指示该字符串是 base64 编码的二进制数据,还是我们要存储的实际本机文本。
为了序列化为 JSON 对象,我想将正文存储为本机字符串,而不是 base64 编码的字符串(如果它是本机文本)。这就是为什么我习惯@JsonIgnoreProperties
不包含该body
属性,而是textEncodedBody
在 JSON 中回显一个。
当我尝试像这样反序列化它时,问题就来了:
val e = Json.parse[Example]("""{'isNativeText': true, 'textEncodedBody': 'hello'}""")
我收到以下错误:
com.codahale.jerkson.ParsingException:无效的 JSON。需要 [body],但找到了 [isNativeText, textEncodedBody]。
显然,我有一个可以工作的构造函数……它只是不是默认的。如何强制 Jerkson 使用这个非默认构造函数?
编辑:我尝试同时使用@JsonProperty
and@JsonCreator
注释,但 jerkson 似乎忽略了这两个。
EDIT2:查看jerkson 案例类序列化源代码,它看起来像一个与其字段同名的案例类方法将以 a@JsonProperty
函数的方式使用 - 即作为 JSON getter。如果我能做到这一点,它将解决我的问题。对 Scala 不太熟悉,我不知道该怎么做;案例类是否有可能具有与其字段之一同名的用户定义方法?
作为参考,下面是导致我得出这个结论的代码......
private val methods = klass.getDeclaredMethods
.filter { _.getParameterTypes.isEmpty }
.map { m => m.getName -> m }.toMap
def serialize(value: A, json: JsonGenerator, provider: SerializerProvider) {
json.writeStartObject()
for (field <- nonIgnoredFields) {
val methodOpt = methods.get(field.getName)
val fieldValue: Object = methodOpt.map { _.invoke(value) }.getOrElse(field.get(value))
if (fieldValue != None) {
val fieldName = methodOpt.map { _.getName }.getOrElse(field.getName)
provider.defaultSerializeField(if (isSnakeCase) snakeCase(fieldName) else fieldName, fieldValue, json)
}
}
json.writeEndObject()
}