Преобразование JSON в одном формате в другой в Scala

Я ищу предложения или библиотеки, которые могут помочь мне преобразовать JSON (с вложенной структурой) из одного формата в другой в Scala.

Я видел, что есть несколько решений на основе JavaScript и Java. Что-нибудь в Скале?

2 ответа

Мне очень нравится библиотека Play JSON. Это API очень чистый и очень быстрый, даже если некоторые части имеют немного более крутой кривой обучения. Вы также можете использовать библиотеку Play JSON, даже если вы не используете остальную часть Play.

https://playframework.com/documentation/2.3.x/ScalaJson

Чтобы преобразовать JSON в объекты Scala (и наоборот), Play использует импликации. E сть Reads тип, который определяет, как преобразовать JSON в тип scala, и Writes Тип, который определяет, как преобразовать объект Scala в JSON.

Например:

case class Foo(a: Int, b: String)

Есть несколько разных маршрутов, которые вы можете выбрать, чтобы конвертировать Foo в JSON. Если ваш объект прост (как Foo), Play JSON может создать функцию преобразования для вас:

implicit val fooReads = Json.reads[Foo]

или вы можете создать пользовательскую функцию преобразования, если вы хотите больше контроля или если ваш тип более сложный. В приведенных ниже примерах используется имя id для собственности a в Foo:

implicit val fooReads = (
  (__ \ "id").read[Int] ~
  (__ \ "name").read[String]
)(Foo)

Writes Тип имеет схожие возможности:

implicit val fooWrites = Json.writes[Foo]

или же

implicit val fooWrites = (
   (JsPath \ "id").write[Int] and
   (JsPath \ "name").write[String]
)(unlift(Foo.unapply))

Вы можете прочитать больше о Reads/Writes (и весь импорт, который вам понадобится) здесь: https://playframework.com/documentation/2.3.x/ScalaJsonCombinators

Вы также можете преобразовать свой JSON, не отображая JSON в / из типов Scala. Это быстро и часто требует меньше шаблонов. Простой пример:

import play.api.libs.json._    

// Only take a single branch from the input json
// This transformer takes the entire JSON subtree pointed to by 
// key bar (no matter what it is)
val pickFoo = (__ \ 'foo).json.pickBranch

// Parse JSON from a string and apply the transformer
val input = """{"foo": {"id": 10, "name": "x"}, "foobar": 100}"""
val baz: JsValue = Json.parse(input)
val foo: JsValue = baz.transform(pickFoo)

Вы можете прочитать больше о преобразовании JSON прямо здесь: https://playframework.com/documentation/2.3.x/ScalaJsonTransformers

Ты можешь использовать Json4s Jackson, С PlayJson вы должны писать неявные преобразования для всех классов. Если нет классов мало, и не будет частых изменений во время разработки, PlayJson вроде бы в порядке. Но, если кейсов больше, я рекомендую использовать json4s. Вам нужно добавить неявное преобразование для разных типов, чтобы json4s понимал это при преобразовании в json.

Вы можете добавить приведенную ниже зависимость в ваш проект, чтобы получить json4s-jackson

"org.json4s" %% "json4s-jackson" % "3.2.11"

Пример кода приведен ниже (с сериализацией и десериализацией):

import java.util.Date
import java.text.SimpleDateFormat

import org.json4s.DefaultFormats
import org.json4s.jackson.JsonMethods._
import org.json4s.jackson.{Serialization}

/**
 * Created by krishna on 19/5/15.
 */
case class Parent(id:Long, name:String, children:List[Child])

case class Child(id:Long, name:String, simple: Simple)

case class Simple(id:Long, name:String, date:Date)

object MainClass extends App {
  implicit val formats = (new DefaultFormats {
    override def dateFormatter = new SimpleDateFormat("yyyy-MM-dd")
  }.preservingEmptyValues)
  val d = new Date()
  val simple = Simple(1L, "Simple", d)
  val child1 = Child(1L, "Child1", simple)
  val child2 = Child(2L, "Child2", simple)
  val parent = Parent(1L, "Parent", List(child1, child2))

  //Conversion from Case Class to Json
  val json = Serialization.write(parent)
  println(json)

  //Conversion from Json to Case Class
  val parentFromJson = parse(json).extract[Parent]
  println(parentFromJson)

}
Другие вопросы по тегам