Преобразование 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)
}