将java.lang.Boolean转换为Scala布尔

时间:2018-09-30 20:06:25

标签: java scala refactoring

我目前正在开发一个Scala应用程序,该应用程序利用Spring-Boot和Swagger发送和接收REST调用。

Swagger和Spring-Boot是纯Java项目,与Scala的兼容性有限,但是我似乎找到了解决此问题的方法。

由于Spring-Boot和Swagger将请求作为Java对象处理(需要使用setter和getter才能工作),因此,我必须将请求视为Java对象,然后将请求转换为更高版本。这是我所做的非常简化的版本


case class ParamsAsJava(includeMovies: java.lang.Boolean = java.lang.Boolean.FALSE, includeTvShows: java.lang.Boolean = java.lang.Boolean.FALSE) {

  def toScala(): Params = {
    Params(
      includeMovies = convertToScala(includeMovies),
      includeTvShows = convertToScala(includeTvShows)
    )
  }

  private def convertToScala(test: java.lang.Boolean): Boolean
  = if (test == null) false else test.booleanValue

}

case class Params(includeMovies: Boolean = false, includeTvShows: Boolean = false)

object Application extends App {

  val test1 = ParamsAsJava(java.lang.Boolean.FALSE, java.lang.Boolean.TRUE).toScala
  val test2 = ParamsAsJava(java.lang.Boolean.TRUE, java.lang.Boolean.TRUE).toScala
  val test3 = ParamsAsJava().toScala
  val test4 = ParamsAsJava(null, null).toScala
  val test5 = ParamsAsJava(null, java.lang.Boolean.TRUE).toScala

  println(s"Test 1 = $test1")
  println(s"Test 2 = $test2")
  println(s"Test 3 = $test3")
  println(s"Test 4 = $test4")
  println(s"Test 5 = $test5")
}

输出

  

测试1 = Params(false,true)

     

测试2 = Params(true,true)

     

测试3 = Params(false,false)

     

测试4 = Params(false,false)

     

测试5 = Params(false,true)


好的...我的问题是:

是否有更简单,更易读的方式来实现这一目标? 我是否必须每次都调用ParamsAsJava.toScala还是有一些很棒 Scala的方式来实现?

3 个答案:

答案 0 :(得分:3)

默认情况下,Spring使用jackson-mapper将JSON请求主体解码为Java类,并将Java类编码为JSON响应。

或者,您可以告诉Spring使用ScalaObjectMapper,它对scala数据类非常有效。

<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-scala_2.12</artifactId>
    <version>2.9.7</version>
</dependency>

然后将Spring配置为在WebMvcConfigurerAdapter中使用ScalaObjectMapper。例子;

import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper
import scala.collection.JavaConverters._

@EnableWebMvc
@Configuration
@PropertySource(Array("classpath:config/default.properties"))
@ComponentScan(Array(
  "com.prayagupd"
))
@Order(HIGHEST_PRECEDENCE)
class MyAppConfig extends WebMvcConfigurerAdapter {

  override def extendMessageConverters(converters: java.util.List[HttpMessageConverter[_]]): Unit = {
    val encodeDecoderOpt = converters.asScala.collectFirst { case p: MappingJackson2HttpMessageConverter => p }

    val jacksonConverter = encodeDecoderOpt.getOrElse(new MappingJackson2HttpMessageConverter)
    jacksonConverter.setObjectMapper(Config.objectMapper)

    if (encodeDecoderOpt.isEmpty) // because converters is mutable
       converters.add(jacksonConverter)
  }
}


object Config {

  @Bean
  def objectMapper: ObjectMapper = {
    new ObjectMapper() with ScalaObjectMapper
  }.registerModule(DefaultScalaModule)
}

应该是这样,现在您可以使用Spring端点定义中的纯scala数据类。例子

@RestController
@CrossOrigin(origins = Array("*"))
@RequestMapping(value = Array("/"))
class MyController @Autowired()(implicit val jacksonObjectMapper: ObjectMapper) {
  import MyController._

  @Async
  @RequestMapping(value = Array("/talk"), method = Array(RequestMethod.POST), consumes = Array(MediaType.APPLICATION_JSON_VALUE), produces = Array(MediaType.APPLICATION_JSON_VALUE))
  def talk(@RequestBody request: MyRequest): MyResponse = {
       // goes here
   }
}

//expose these in client jar if you want
object MyController {
  final case class MyRequest(includeMovies: Boolean, includeTvShows: Boolean, somethingElse: List[String])

  final case class MyResponse(whatever: String)
}

答案 1 :(得分:2)

  1. 您不需要每次都写出java.lang.blah

    ParamsAsJava(java.lang.Boolean.FALSE, java.lang.Boolean.TRUE)
    

    只需使用

    ParamsAsJava(false, true)
    

    相反。自动装箱还没有到位。

  2. 要摆脱toScala,请在Params伴随对象中定义一个隐式转换:

    object Params {
      implicit def params_j2s(p: ParamsAsJava): Params = p.toScala()
    }
    

    现在您可以写:

    val test1: Params = ParamsAsJava(true, false)
    

    当然,如果您不是在真空中定义此变量,而是将其传递给方法,则会自动推断出正确的类型,并且将隐式转换对象。

  3. 无需在()中使用括号def toScala(),该方法没有副作用。

答案 2 :(得分:1)

我使用了scala.Boolean boxunbox方法。