Как запретить json4s отображать нулевые значения?

Как предотвратить рендеринг нулевых значений json4s при преобразовании объекта/JObject в строку json?

В Джексоне вы можете сделать это, выполнив следующие действия:

mapper.setSerializationInclusion(Include.NON_NULL)

Как я могу сделать то же самое в json4s?

Пример

import org.json4s.jackson.JsonMethods._
import org.json4s.jackson.Serialization
import org.json4s.{Extraction, NoTypeHints}

case class Book(title: String, author: String)

implicit val formats = Serialization.formats(NoTypeHints)

val bookJValue = Extraction.decompose(Book(null, "Arthur C. Clark"))
# JObject(List((title,JNull), (author,JString(Arthur C. Clark))))

val compacted = compact(render(bookJValue))
# {"title":null,"author":"Arthur C. Clark"}

Я бы хотел, чтобы сжатый json был таким:

{"author":"Arthur C. Clark"}

person vrepsys    schedule 23.10.2015    source источник


Ответы (2)


case class Book(title: Option[String], author: String)
val b = Book(None, "Arthur C. Clark")
println(write(b))
res1:> {"author":"Arthur C. Clark"}

Вы можете использовать Option для определения переменной. если нет, эта переменная не будет сериализована.

Есть еще один способ сделать это, используя removeField после decompose вашего object, например:

bookJValue.removeFile {
   case (_, JNull) => true
   case _ => false
}
person chengpohi    schedule 23.10.2015
comment
В моем случае я не контролирую код, в котором определена Книга. Извините, мой вопрос был недостаточно ясен. Есть ли другой способ сделать это? - person vrepsys; 23.10.2015

Вы можете легко создать свой собственный сериализатор. Подписывайтесь на меня.

Прежде всего, сделайте небольшое изменение в formats:

implicit val formats = DefaultFormats + new BookSerializer

После этого создайте свой собственный сериализатор/десериализатор:

class BookSerializer extends CustomSerializer[Book](format => (
  {
    case JObject(JField("title", JString(t)) :: JField("author", JString(a)) ::Nil) =>
      new Book(t, a)
  },
  {
    case x @ Book(t: String, a: String) =>
      JObject(JField("title", JString(t)) ::
        JField("author", JString(a)) :: Nil)
    case Book(null, a: String) =>
      JObject(JField("author", JString(a)) :: Nil) // `title` == null
  }
  ))

Первая часть — это десериализатор (преобразование данных из json в класс case), а вторая — сериализатор (преобразование из класса case в json). Я добавил случай title == null. Вы можете легко добавить столько дел, сколько вам нужно.

Весь список:

import org.json4s.jackson.JsonMethods._
import org.json4s.{DefaultFormats, Extraction}
import org.json4s._


case class Book(title: String, author: String)

implicit val formats = DefaultFormats + new BookSerializer
class BookSerializer extends CustomSerializer[Book](format => (
  {
    case JObject(JField("title", JString(t)) :: JField("author", JString(a)) ::Nil) =>
      new Book(t, a)
  },
  {
    case x @ Book(t: String, a: String) =>
      JObject(JField("title", JString(t)) ::
        JField("author",   JString(a)) :: Nil)
    case Book(null, a: String) =>
      JObject(JField("author",   JString(a)) :: Nil) // `title` == null
  }
  ))

val bookJValue = Extraction.decompose(Book(null, "Arthur C. Clark"))
val compacted = compact(render(bookJValue))

Выход:

compacted: String = {"author":"Arthur C. Clark"}

Дополнительную информацию можно найти на странице проекта json4s.

person ilyakhov    schedule 23.10.2015