通过 scala-pickling 序列化后从 json 中删除 tpe
remove tpe from json after serialization via scala-pickling
有没有一种简单的方法可以在对象内部没有 "tpe" 字段的情况下序列化为 json?
我需要将 case classes 序列化为 json 结构,然后通过网络发送它们(它们将来不会被反序列化)。我有一个特定的 api,所以..我不需要额外的字段。
对于 class Person
如下图所示:
case class Person(Name: String, Age: int, CandyLover: Boolean)
我想看以下内容:
{
"Name": "Paul",
"Age": 23,
"CandyLover": true
}
我建议您看一下 spray-json 或 argonaut。或者播放-json 如果您已经在使用 Play.
Scala pickling 并不是真正的 json 库,它不是为 public API 生成 JSON 而创建的,它不灵活,您无法定义JSON 协议优先,然后提供酸洗序列化以匹配协议。 Pickling 用于计算机到计算机的序列化,没有人真正关心应用程序之间传输的字节。
可能最简单的方法是以某种方式将 Hint
传递给 JSONPickleBuilder
。快速的方法是通过从 PickleTools
.
调用 hintStaticallyElidedType()
方法来覆盖 JSONPickleFormat
中的构建器
下面是演示它的代码片段:
import org.specs2.matcher.JsonMatchers
import org.specs2.mutable.Specification
import org.specs2.specification.Scope
import scala.pickling.Defaults._
import scala.pickling.json.{JSONPickleBuilder, JSONPickleFormat, JsonFormats}
import scala.pickling.{Output, PBuilder, PickleTools, StringOutput}
class PersonJsonFormatsTest extends Specification with JsonMatchers {
trait Context extends Scope with PersonJsonFormats
trait PersonJsonFormats extends JsonFormats {
override implicit val pickleFormat: JSONPickleFormat = new PersonJSONPickleFormat
}
class PersonJSONPickleFormat extends JSONPickleFormat {
override def createBuilder() = new JSONPickleBuilder(this, new StringOutput) with PickleTools {
hintStaticallyElidedType()
}
override def createBuilder(out: Output[String]): PBuilder = new JSONPickleBuilder(this, out) with PickleTools {
hintStaticallyElidedType()
}
}
"Pickle" should {
"Serialize Person without $type field in resulting JSON" in new Context {
case class Person(Name: String, Age: Int, CandyLover: Boolean)
val pickledPersonObject = Person("Paul", 23, CandyLover = true).pickle
println(pickledPersonObject.value)
pickledPersonObject.value must not */("$type" → ".*".r)
}
}
}
println(pickledPersonObject.value)
的输出将是您需要的:
{
"Name": "Paul",
"Age": 23,
"CandyLover": true
}
这样您将与进一步的 pickle 更新保持一致。
P.S。如果有人知道更优雅、更方便的方式来达到相同的行为 - 请告诉我们:-)
对于 scala-pickling 0.10.x:
import scala.pickling._
import scala.pickling.json.{JSONPickle, JSONPickleBuilder, JSONPickleFormat, JsonFormats}
import scala.pickling.pickler.AllPicklers
object serialization extends JsonFormats with Ops with AllPicklers {
override implicit val pickleFormat: JSONPickleFormat = new JSONPickleFormat {
private def setHints(h: Hintable): Unit = {
h.hintStaticallyElidedType()
h.hintDynamicallyElidedType()
}
override def createBuilder(): JSONPickleBuilder = {
val builder = super.createBuilder()
setHints(builder)
builder
}
override def createBuilder(out: Output[String]): PBuilder = {
val builder = super.createBuilder(out)
setHints(builder)
builder
}
override def createReader(pickle: JSONPickle): PReader = {
val reader = super.createReader(pickle)
setHints(reader)
reader
}
}
}
object SerializationTest extends App {
import serialization._
case class Person(firstName: String, lastName: String)
val pickle: JSONPickle = Person("Evelyn", "Patterson").pickle
val jsonString: String = pickle.value // {"firstName": "Evelyn","lastName": "Patterson"}
val person: Person = jsonString.unpickle[Person]
}
对于 scala-pickling 0.11.x:
import scala.pickling._
import scala.pickling.json.{JSONPickle, JSONPickleBuilder, JSONPickleFormat}
import scala.pickling.pickler.AllPicklers
object serialization extends AllPicklers {
private final class CustomJSONPickleFormat(tag: FastTypeTag[_]) extends JSONPickleFormat {
private def setHints(h: Hintable) {
h.hintElidedType(tag)
}
override def createBuilder(): JSONPickleBuilder = {
val b = super.createBuilder()
setHints(b)
b
}
override def createBuilder(out: Output[String]): PBuilder = {
val b = super.createBuilder(out)
setHints(b)
b
}
override def createReader(pickle: JSONPickle): PReader = {
val b = super.createReader(pickle)
setHints(b)
b
}
}
implicit val staticOnly = static.StaticOnly // for compile time serialization methods generation
implicit final class EncodeDecodeOps[T](picklee: T) {
def encode(implicit pickler: Pickler[T]): String = {
val pickleFormat = new CustomJSONPickleFormat(pickler.tag)
functions.pickle(picklee)(pickleFormat, pickler).value
}
def decode[A](implicit c: T => String, unpickler: Unpickler[A]): A = {
val pickleFormat = new CustomJSONPickleFormat(unpickler.tag)
functions.unpickle[A](json.JSONPickle(picklee))(unpickler, pickleFormat)
}
}
}
case class Person(firstName: String, lastName: String) {
@transient var x = "test"
}
object SerializationTest extends App {
import serialization._
val jsonString = Person("Lisa", "Daniels").encode
println(jsonString)
val person = jsonString.decode[Person]
println(person)
}
有没有一种简单的方法可以在对象内部没有 "tpe" 字段的情况下序列化为 json? 我需要将 case classes 序列化为 json 结构,然后通过网络发送它们(它们将来不会被反序列化)。我有一个特定的 api,所以..我不需要额外的字段。
对于 class Person
如下图所示:
case class Person(Name: String, Age: int, CandyLover: Boolean)
我想看以下内容:
{
"Name": "Paul",
"Age": 23,
"CandyLover": true
}
我建议您看一下 spray-json 或 argonaut。或者播放-json 如果您已经在使用 Play.
Scala pickling 并不是真正的 json 库,它不是为 public API 生成 JSON 而创建的,它不灵活,您无法定义JSON 协议优先,然后提供酸洗序列化以匹配协议。 Pickling 用于计算机到计算机的序列化,没有人真正关心应用程序之间传输的字节。
可能最简单的方法是以某种方式将 Hint
传递给 JSONPickleBuilder
。快速的方法是通过从 PickleTools
.
hintStaticallyElidedType()
方法来覆盖 JSONPickleFormat
中的构建器
下面是演示它的代码片段:
import org.specs2.matcher.JsonMatchers
import org.specs2.mutable.Specification
import org.specs2.specification.Scope
import scala.pickling.Defaults._
import scala.pickling.json.{JSONPickleBuilder, JSONPickleFormat, JsonFormats}
import scala.pickling.{Output, PBuilder, PickleTools, StringOutput}
class PersonJsonFormatsTest extends Specification with JsonMatchers {
trait Context extends Scope with PersonJsonFormats
trait PersonJsonFormats extends JsonFormats {
override implicit val pickleFormat: JSONPickleFormat = new PersonJSONPickleFormat
}
class PersonJSONPickleFormat extends JSONPickleFormat {
override def createBuilder() = new JSONPickleBuilder(this, new StringOutput) with PickleTools {
hintStaticallyElidedType()
}
override def createBuilder(out: Output[String]): PBuilder = new JSONPickleBuilder(this, out) with PickleTools {
hintStaticallyElidedType()
}
}
"Pickle" should {
"Serialize Person without $type field in resulting JSON" in new Context {
case class Person(Name: String, Age: Int, CandyLover: Boolean)
val pickledPersonObject = Person("Paul", 23, CandyLover = true).pickle
println(pickledPersonObject.value)
pickledPersonObject.value must not */("$type" → ".*".r)
}
}
}
println(pickledPersonObject.value)
的输出将是您需要的:
{
"Name": "Paul",
"Age": 23,
"CandyLover": true
}
这样您将与进一步的 pickle 更新保持一致。
P.S。如果有人知道更优雅、更方便的方式来达到相同的行为 - 请告诉我们:-)
对于 scala-pickling 0.10.x:
import scala.pickling._
import scala.pickling.json.{JSONPickle, JSONPickleBuilder, JSONPickleFormat, JsonFormats}
import scala.pickling.pickler.AllPicklers
object serialization extends JsonFormats with Ops with AllPicklers {
override implicit val pickleFormat: JSONPickleFormat = new JSONPickleFormat {
private def setHints(h: Hintable): Unit = {
h.hintStaticallyElidedType()
h.hintDynamicallyElidedType()
}
override def createBuilder(): JSONPickleBuilder = {
val builder = super.createBuilder()
setHints(builder)
builder
}
override def createBuilder(out: Output[String]): PBuilder = {
val builder = super.createBuilder(out)
setHints(builder)
builder
}
override def createReader(pickle: JSONPickle): PReader = {
val reader = super.createReader(pickle)
setHints(reader)
reader
}
}
}
object SerializationTest extends App {
import serialization._
case class Person(firstName: String, lastName: String)
val pickle: JSONPickle = Person("Evelyn", "Patterson").pickle
val jsonString: String = pickle.value // {"firstName": "Evelyn","lastName": "Patterson"}
val person: Person = jsonString.unpickle[Person]
}
对于 scala-pickling 0.11.x:
import scala.pickling._
import scala.pickling.json.{JSONPickle, JSONPickleBuilder, JSONPickleFormat}
import scala.pickling.pickler.AllPicklers
object serialization extends AllPicklers {
private final class CustomJSONPickleFormat(tag: FastTypeTag[_]) extends JSONPickleFormat {
private def setHints(h: Hintable) {
h.hintElidedType(tag)
}
override def createBuilder(): JSONPickleBuilder = {
val b = super.createBuilder()
setHints(b)
b
}
override def createBuilder(out: Output[String]): PBuilder = {
val b = super.createBuilder(out)
setHints(b)
b
}
override def createReader(pickle: JSONPickle): PReader = {
val b = super.createReader(pickle)
setHints(b)
b
}
}
implicit val staticOnly = static.StaticOnly // for compile time serialization methods generation
implicit final class EncodeDecodeOps[T](picklee: T) {
def encode(implicit pickler: Pickler[T]): String = {
val pickleFormat = new CustomJSONPickleFormat(pickler.tag)
functions.pickle(picklee)(pickleFormat, pickler).value
}
def decode[A](implicit c: T => String, unpickler: Unpickler[A]): A = {
val pickleFormat = new CustomJSONPickleFormat(unpickler.tag)
functions.unpickle[A](json.JSONPickle(picklee))(unpickler, pickleFormat)
}
}
}
case class Person(firstName: String, lastName: String) {
@transient var x = "test"
}
object SerializationTest extends App {
import serialization._
val jsonString = Person("Lisa", "Daniels").encode
println(jsonString)
val person = jsonString.decode[Person]
println(person)
}