【问题标题】:Jackson / No serializer found for class杰克逊/没有找到类的序列化程序
【发布时间】:2014-02-17 08:49:49
【问题描述】:

Neo4j 服务器提供了一个处理 Json 格式的 REST api。 我使用 spring-data-neo4j 轻松地将域对象(在 Scala 中)映射到 neo4j 节点。 这是我的用户节点的示例:

@NodeEntity
class User(@Indexed @JsonProperty var id: UserId)

UserId 是一个值对象:

final case class UserId(value: String) {
  override def toString = value
}

object UserId {
  def validation(userId: String): ValidationNel[IllegalUserFailure, UserId] =
    Option(userId).map(_.trim).filter(!_.isEmpty).map(userId => new UserId(userId)).toSuccess(NonEmptyList[IllegalUserFailure](EmptyId))
}

在运行时,我收到了这个错误:

Execution exception[[RuntimeException: org.codehaus.jackson.map.JsonMappingException: No      serializer found for class com.myApp.domain.model.user.UserId and no properties discovered to       create BeanSerializer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS)        ) (through reference chain: java.util.HashMap["value"])]]

然后,我在网上看到了这个小article,解释了一个解决方案。

我最终得到了这个User 类:

@NodeEntity
@JsonAutoDetect(Array(JsonMethod.NONE))
class User (@Indexed @JsonProperty var id: UserId)

我还尝试将@JsonProperty 放在UserId 值对象本身上,如下所示:

JsonAutoDetect(Array(JsonMethod.NONE))
final case class UserId(@JsonProperty value: String) {
  override def toString = value
}

但我仍然得到完全相同的错误。

使用 Scala 的人是否已经遇到过这个问题?

【问题讨论】:

    标签: scala serialization neo4j jackson spring-data-neo4j


    【解决方案1】:

    我认为您的问题是案例类不会生成杰克逊期望的 JavaBean 样板(或适当注释的成员字段)。比如我相信Scala会在UserId生成这个方法:

    public java.lang.String value();
    

    杰克逊不知道该怎么办。它不是可识别的字段或 JavaBean 样式的方法(即 getValue()setValue())。

    我还没有使用它,但您可能想尝试将 jackson-module-scala 作为 Jackson 周围更支持 Scala 的包装器。另一个选项是spray-json

    【讨论】:

    • 这是有道理的。但是,我不明白为什么只有标记为@Indexed 的字段失败了。如果我将注释放在UserIdfield 上,则整个过程没有任何杰克逊注释。
    • 我猜这与User 是一个常规类有关(而UserId 是一个案例类)。我喜欢 Jackson,但我强烈建议您使用支持 Scala 的 JSON 序列化器/反序列化器,正如我所说,它可能只是 Jackson 包装器。就我个人而言,我对这种细枝末节不感兴趣,我希望这些东西能够正常工作,这样我就可以专注于有趣的问题。
    【解决方案2】:

    错误的原因是您似乎使用的 Jackson 版本 (1.x) 未将“value”属性与构造函数参数匹配。当应用于构造函数时,@JsonProperty 通常需要一个名称参数来匹配参数和属性;使用您当前的设置,我相信以下方法会起作用:

    case class UserId @JsonCreator() (@JsonProperty("value") value: String)
    

    Jackson Scala 模块还为 Scala-isms 提供了更多支持,并且可能在没有任何 Jackson 特定注释的情况下处理 UserId 类。也就是说,您的 Jackson 版本相当旧(当前最新版本为 2.3.1),升级对您的配置而言可能并非易事。

    【讨论】:

    • 行得通! :) 我错过了注释@JsonCreator()。我目前使用旧版本,因为它是 Spring-data-neo4j-rest 带来的。如果可能的话,我会要求他们更新它。非常感谢 ! :)
    • 但是,@Indexed 不再考虑。我应该在哪里放置@Indexed 注释?我试过这个:case class UserId @JsonCreator()(@JsonProperty("value") @Indexed value: String) 或者这个:class User(@Indexed @JsonProperty var id: UserId) ..
    • 需要设置@Indexed注解的目标出现在字段上,这样neo4j才能找到。语法是:@(Indexed @field),其中field 在 Scala 2.9 中是 scala.annotation.target.field,在 Scala 2.10 中是 scala.annotation.meta.field
    • 其实我使用这个自定义注解来避免Scala注解的问题:type Indexed = org.springframework.data.neo4j.annotation.Indexed@field。它可以解决问题还是你的语法有不同的行为?
    • 刚刚看了spring-data-neo4j的源码。我可以确认恕我直言,自定义类型是不可能的。实际上,索引属性默认设置为“数字”,然后代码是:public static boolean isNumeric(final Class<?> fieldType) { return (fieldType.isPrimitive() && !fieldType.equals(boolean.class) && !fieldType.equals(void.class)) || fieldType.equals(Character.class) || (fieldType.getName().startsWith("java.lang") && Number.class.isAssignableFrom(fieldType)); } 只有原语是可能的。这太糟糕了,但我希望这会发展;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-16
    • 1970-01-01
    • 1970-01-01
    • 2011-07-03
    • 2020-12-24
    • 2015-04-07
    相关资源
    最近更新 更多