【问题标题】:@JsonIgnore serialising Scala case class property using Jackon and Json4s@JsonIgnore 使用 Jackson 和 Json4s 序列化 Scala 案例类属性
【发布时间】:2014-10-28 13:45:44
【问题描述】:

我试图阻止 Scala case class 的属性之一被序列化。我尝试使用通常的@JsonIgnore 注释有问题的属性,并且我还尝试将@JsonIgnoreProperties(Array("property_name")) 附加到case class。两者似乎都没有达到我想要的。

这是一个小例子:

import org.json4s._
import org.json4s.jackson._
import org.json4s.jackson.Serialization
import org.json4s.jackson.Serialization.{read, write}
import com.fasterxml.jackson.annotation._

object Example extends App {

    @JsonIgnoreProperties(Array("b"))
    case class Message(a: String, @JsonIgnore b: String)

    implicit val formats = Serialization.formats(NoTypeHints)
    val jsonInput = """{ "a": "Hello", "b":"World!" }"""
    val message = read[Message](jsonInput)
    println("Read " + message) // "Read Message(Hello,World!)

    val output = write(message) 
    println("Wrote " + output) // "Wrote {"a":"Hello","b":"World!"}"
}

【问题讨论】:

  • 您是否尝试使用 @JsonProperty("b") b: String 而不是 @JsonIgnore b: String 来注释“b”?我相信应该可以解决这个问题。

标签: scala jackson json4s


【解决方案1】:

使用jackson-databind 2.8.6jackson-module-scala 2.8.4

"com.fasterxml.jackson.core" % "jackson-databind" % "2.8.6",
"com.fasterxml.jackson.module" % "jackson-module-scala_2.11" % "2.8.4"

只有@JsonIgnoreProperties 可以正常工作,

示例案例类如下,我忽略了"eventOffset""hashValue"

import java.util.Date

import com.fasterxml.jackson.annotation.{JsonIgnore, JsonIgnoreProperties}
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper

@JsonIgnoreProperties(Array("eventOffset", "hashValue"))
case class TestHappenedEvent(eventOffset: Long, hashValue: Long, eventType: String,
                             createdDate: Date, testField: String) {

  def this() {
    this(0, 0, "", new Date(), "")
  }

  def toJSON(): String = {
    val objectMapper = new ObjectMapper() with ScalaObjectMapper
    objectMapper.registerModule(DefaultScalaModule)

    val data = this.copy()
    val stream = new ByteArrayOutputStream()
    objectMapper.writeValue(stream, data)
    stream.toString
  }
}

测试

import org.scalatest.FunSuite
import spray.json._

class BaseEventSpecs extends FunSuite {

  val abstractEvent = TestHappenedEvent(0, 1, "TestHappenedEvent", new Date(2017, 10, 28), "item is sold")

  test("converts itself to JSON") {

    assert(abstractEvent.toJSON().parseJson ==
      """
        {
          "eventType":"TestHappenedEvent",
          "createdDate":61470000000000,
          "testField":"item is sold"
        }
      """.stripMargin.parseJson)
  }

}

【讨论】:

    【解决方案2】:

    将您的@JsonIgnore 更改为@JsonProperty("b")。您已正确声明忽略属性 'b 但尚未将 'b 注释为属性。

    @JsonIgnoreProperties(Array("b"))
    case class Message(a: String, @JsonProperty("b") b: String)
    

    【讨论】:

    • 这太奇怪了,先注释为json字符串属性然后忽略。
    • 对于 Jackson 2.8.3、Scala 2.11.8,不再需要单独注释 JsonProperty
    • 使用 String 命名它是一个好习惯,因为 JsonIgnoreProperties 使用属性名称作为字符串,并且该名称可能会从其他上下文重命名,从而打破“忽略”。