繁体   English   中英

球衣/杰克逊中的Scala枚举序列化对我不起作用

[英]Scala enumeration serialization in jersey/jackson is not working for me

我已经阅读了有关枚举处理的jackson-module-scala页面( https://github.com/FasterXML/jackson-module-scala/wiki/Enumerations )。 我仍然无法正常工作。 基本代码如下所示:

@Path("/v1/admin")
@Produces(Array(MediaType.APPLICATION_JSON + ";charset=utf-8"))
@Consumes(Array(MediaType.APPLICATION_JSON + ";charset=utf-8"))
class RestService {

  @POST
  @Path("{type}/abort")
  def abortUpload(@PathParam("type") typeName: ResourceTypeHolder) {
    ...
  }
}

object ResourceType extends Enumeration {
    type ResourceType = Value
    val ssr, roadsegments, tmc, gab, tne = Value
}

class ResourceTypeType extends TypeReference[ResourceType.type]
case class ResourceTypeHolder(
  @JsonScalaEnumeration(classOf[ResourceTypeType])
  resourceType:ResourceType.ResourceType
)

这应该是这样工作的,对吗? 我仍然收到这些错误:

Following issues have been detected:
WARNING: No injection source found for a parameter of type public void no.tull.RestService.abortUpload(no.tull.ResourceTypeHolder) at index 0.

unavailable
org.glassfish.jersey.server.model.ModelValidationException: Validation of the application resource model has failed during application initialization.
[[FATAL] No injection source found for a parameter of type public void no.tull.RestService.abortUpload(no.tull.ResourceTypeHolder) at index 0.; source='ResourceMethod{httpMethod=POST, consumedTypes=[application/json; charset=utf-8], producedTypes=[application/json; charset=utf-8], suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS, invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class no.tull.RestService, handlerConstructors=[org.glassfish.jersey.server.model.HandlerConstructor@7ffe609f]}, definitionMethod=public void no.tull.RestService.abortUpload(no.tull.ResourceTypeHolder), parameters=[Parameter [type=class no.tull.ResourceTypeHolder, source=type, defaultValue=null]], responseType=void}, nameBindings=[]}']
    at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:467)
    at org.glassfish.jersey.server.ApplicationHandler.access$500(ApplicationHandler.java:163)
    at org.glassfish.jersey.server.ApplicationHandler$3.run(ApplicationHandler.java:323)
    at org.glassfish.jersey.internal.Errors$2.call(Errors.java:289)
    at org.glassfish.jersey.internal.Errors$2.call(Errors.java:286)

我还组装了一个很小的可运行项目(同时尝试消除任何其他复杂性)来说明问题: project.tgz

更新:创建了一个sbt文件来查看gradle是否正在构建一个奇怪的版本。 得到了相同的结果,但这是build.sbt

name := "project"

version := "1.0"

scalaVersion := "2.10.4"

val jacksonVersion = "2.4.1"
val jerseyVersion = "2.13"

libraryDependencies ++= Seq(
  "com.fasterxml.jackson.core" % "jackson-annotations" % jacksonVersion,
  "com.fasterxml.jackson.core" % "jackson-databind" % jacksonVersion,
  "com.fasterxml.jackson.jaxrs" % "jackson-jaxrs-json-provider" % jacksonVersion,
  "com.fasterxml.jackson.jaxrs" % "jackson-jaxrs-base" % jacksonVersion,
  "com.fasterxml.jackson.module" % "jackson-module-scala_2.10" % jacksonVersion,
  "org.glassfish.jersey.containers" % "jersey-container-servlet-core" % jerseyVersion
)

seq(webSettings :_*)

libraryDependencies ++= Seq(
  "org.eclipse.jetty" % "jetty-webapp" % "9.1.0.v20131115" % "container",
  "org.eclipse.jetty" % "jetty-plus"   % "9.1.0.v20131115" % "container"
)

...这是project / plugins.sbt

addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "0.9.0")

您的tarball似乎有一些问题。

您需要向Jackson添加一些Scala模块,才能使用任何Scala功能。 可以这样做:

val jsonObjectMapper = new ObjectMapper()
jsonObjectMapper.registerModule(DefaultScalaModule)
val jsonProvider: JacksonJsonProvider = new JacksonJsonProvider(jsonObjectMapper)

根据这个工作中的泽克-杰克逊的例子 您还需要将org.glassfish.jersey.jackson.JacksonFeature注入到Jersey jersey-media-json-jackson找到的Jersey中。 我的RestApplication.scala像这样出来

import javax.ws.rs.core.Application
import javax.ws.rs.ext.{ContextResolver, Provider}

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.google.common.collect.ImmutableSet
import org.glassfish.jersey.jackson.JacksonFeature

@Provider
class ObjectMapperProvider extends ContextResolver[ObjectMapper] {
  val defaultObjectMapper = {
    val jsonObjectMapper = new ObjectMapper()
    jsonObjectMapper.registerModule(DefaultScalaModule)
    jsonObjectMapper
  }

  override def getContext(typ: Class[_]): ObjectMapper = {
    defaultObjectMapper
  }
}

class RestApplication extends Application {
  override def getSingletons: java.util.Set[AnyRef] = {
    ImmutableSet.of(
      new RestService,
      new ObjectMapperProvider,
      new JacksonFeature
    )
  }
}

但是,真正的问题是@PathParam批注。 此代码路径根本不会调用Jackson。 但是,有趣的是,Jersey似乎普遍支持解析为具有单个字符串的构造函数的任何类型。 因此,如果您修改ResourceTypeHolder ,则毕竟可以获得所需的功能。

case class ResourceTypeHolder(@JsonScalaEnumeration(classOf[ResourceTypeType]) resourceType:ResourceType.ResourceType) {
  def this(name: String) = this(ResourceType.withName(name))
}

您也许可以将注射枚举支持者的枚举持有者的通用支持添加到Jersey。 但是,dropwizard-scala并没有实现这一目标,该项目也将遭受与使用Jersey相同的命运。 因此,我想这是不可能的,或者仅仅是对于任何人完成这项工作而言不够普遍。 当涉及到枚举时,我倾向于保留Java语言。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM