質問

Neo4j server provides a REST api dealing with Json format. I use spring-data-neo4j to map a domain object (in Scala) to a neo4j node easily. Here's an example of my User node:

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

UserId being a value object:

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))
}

At runtime, I got this error:

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"])]]

Then, I came across this little article on the web, explaining a solution.

I ended up with this User class:

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

I also tried to put the @JsonProperty on the UserId value object itself like this:

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

but I still get exactly the same error.

Did someone using Scala already had this issue?

役に立ちましたか?

解決

I think your problem is that case classes don't generate the JavaBean boilerplate (or member fields annotated appropriately) Jackson expects. For example, I believe Scala generates this method in UserId:

public java.lang.String value();

Jackson doesn't know what to do with that. It isn't a recognizable field or a JavaBean-style method (i.e. getValue() or setValue()).

I haven't yet used it, but you might want to try jackson-module-scala as a more Scala-aware wrapper around Jackson. Another option is spray-json.

他のヒント

The reason for the error is that the version of Jackson that you appear to be using (1.x) is not matching up the "value" property to the constructor argument. When applied to constructors, @JsonProperty usually requires a name parameter to match up parameters to properties; with your current setup, I believe the following would work:

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

The Jackson Scala Module also provides more support for Scala-isms, and might possibly handle the UserId class without any Jackson-specific annotations. That said, your version of Jackson is quite old (the current latest version is 2.3.1), and upgrading might not be trivial for your configuration.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top