squbs-6. 序列化和反序列化

原文地址:Marshalling and Unmarshalling

概览

序列化和反序列化同时在客户端和服务端使用。在服务端,它用于映射进来的请求至Scala或Java对象来输出相应。相似的,在客户端,它将用于序列化对象来传出HTTP请求和从进来的相应中反序列化它。这里有多种内容格式来序列化和反序列化,常见的有JSON和XML。

Akka HTTP 提供序列化/反序列化功能在 Scala marshalling/unmarshalling 和 Java marshalling/unmarshalling中阐述。同样的,有为Akka HTTP提供其他开源的序列化和反序列化,可用于不同格式和使用不同对象的序列化反序列实现。

squbs为手动序列化/反序列化提供JAVA API,以及添加在 Scala/Java 跨语言环境中工作工具。手动访问解析器和反解析器对于基于流的应用是有用的,在某些工作需要在流阶段完成。他同时对测试解析器配置式有用的,来保证实现正确的格式。

这篇文章讨论squbs提供的解析器和反解析器,你可以使用工具来手动调用这些解析器和反解析器。这个文档不再 作为 Akka HTTP路由DSL的一部分来阐述解析器和反解析器的作用。请查看Akka HTTP 路由 DSL Scala 和 Java 中的解析指令(包括在这篇文章中提供的)来使用解析器。

依赖

在你的 build.sbt 或scala构建文件中加入以下依赖:

"org.squbs" %% "squbs-ext" % squbsVersion

用法

JacksonMapperSupport

JacksonMapperSupport提供基于当前流行的Jackson类库的JSON解析器和泛解析器。它允许全局的和单独的Jackson ObjectMapper配置。
更多关于ObjectMapper的配置细节请参见Jackson Data Binding documentation

Scala
import org.squbs.marshallers.json.JacksonMapperSupport._

自动和手动解析器都将在这个包中隐式的使用这个解释器。下面这个代码的例子展示了通过ObjectMapper配置DefaultScalaModule的不同方式。

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import org.squbs.marshallers.json.JacksonMapperSupport

/* To use DefaultScalaModule for all classes.
 */

JacksonMapperSupport.setDefaultMapper(
  new ObjectMapper().registerModule(DefaultScalaModule))


/* To register a 'DefaultScalaModule' for marshalling a
 * specific class, overrides global configuration for
 * this class.
 */

JacksonMapperSupport.register[MyScalaClass](
  new ObjectMapper().registerModule(DefaultScalaModule))
Java

解析器和反解析器可以从JacksonMapperSupportmarshallerunmarshaller方法中获取,将类的实例类型传递来序列化/反序列化如下:

import akka.http.javadsl.marshalling.Marshaller;
import akka.http.javadsl.model.HttpEntity;
import akka.http.javadsl.model.RequestEntity;
import akka.http.javadsl.unmarshalling.Unmarshaller;

import static org.squbs.marshallers.json.JacksonMapperSupport.*;

Marshaller myMarshaller =
    marshaller(MyClass.class);

Unmarshaller myUnmarshaller =
    unmarshaller(MyClass.class);

在本文中的讨论中,这些解析器可以作为Akka HTTP Routing DSL 的一部分或 invoking marshalling/unmarshalling的一部分使用。

下面的例子通过 ObjectMapper配置 DefaultScalaModule

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.scala.DefaultScalaModule;
import org.squbs.marshallers.json.JacksonMapperSupport;

/* Globally registers the 'DefaultScalaModule'.
 */
 
JacksonMapperSupport.setDefaultMapper(
  new ObjectMapper().registerModule(new DefaultScalaModule()));


/* This example below registers the 'DefaultScalaModule'
 * just for 'MyClass'
 */

JacksonMapperSupport.register(MyClass.class
  new ObjectMapper().registerModule(new DefaultScalaModule()));

XLangJsonSupport

XLangJsonSupport通过委托序列化和反序列化加入跨语言支持:

  • Json4s for Scala classes
  • Jackson for Java classes

这些通常是每个语言首选的解析器,无需更多的配置,他们即支持特定语言约定。他们同样对不同的约定通常有更好的优化。

然而,这个使用Json4s或Jackson的决定取决于用户序列化/反序列化传入的对象的类型。如果你有一个混合对象层次结构,你可能需要配置序列化/反序列化工具来支持不同的约定,如下所示:

  • Scala case class 引用Java Beans. 如果顶级对象是一个 Scala case class。 Json4s将被选择。然而它不知道如何序列化/反序列化 Java Beans。一个自定义的序列化需要加入到Json4来处理Java Bean。

  • Java Beans引用 Scala case class。如果顶级对象是Java Bean,Jackson将被选择。Jackson默认不支持如何序列化/反序列化这些 case class。你需要注册 DefaultScalaModule至Jackson ObjectMapper 来处理这些情况。

一个通用的序列化/反序列化混合语言对象层次结构的准则:除非Json4s优化是首选的,配置Jackson处理Scala更简单,只需要向ObjectMapper注册DefaultScalaModule

JacksonMapperSupport,它支持每种类型的解析器和反解析器配置。它允许配置Json4s 和 Jackson。

Scala

你只需要导入 XLangJsonSupport._来暴露它在解析器和反解析器使用Scala代码范围内的隐藏成员。

自动和手动解析器将隐式使用这个包提供的解析器。下面提供配置XLangJsonSupport的例子:

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule
import org.json4s.{DefaultFormats, jackson, native}
import org.squbs.marshallers.json.XLangJsonSupport

/* The following configures the default settings
 * for 'XLangJsonSupport'
 */

// Adds ParameterNamesModule to Jackson
XLangJsonSupport.setDefaultMapper(
  new ObjectMapper().registerModule(new ParameterNamesModule())
  
// Tells Json4s to use native serialization
XLangJsonSupport.setDefaultSerialization(native.Serialization)

// Adds MySerializer to the serializers used by Json4s
XLangJsonSupport.setDefaultFormats(DefaultFormats + MySerializer)


/* The following configures XLangJsonSupport for specific class.
 * Namely, it configures for 'MyClass' and 'MyOtherClass'.
 */

// Use ParameterNamesModule for mashal/unmarshal MyClass
XLangJsonSupport.register[MyClass](new ParameterNamesModule()))

// Use Json4s Jackson serialization for MyOtherClass
XLangJsonSupport.register[MyOtherClass](jackson.Serialization)

// Use MySerializer Json4s serializer for MyOtherClass
XLangJsonSupport.register[MyOtherClass](DefaultFormats + MySerializer)
Java

解析器和反解析器可以从XLangJsonSupport中的 marshallerunmarshaller方法中获取,传递类实例的类型来序列化/反序列化,如下:

import akka.http.javadsl.marshalling.Marshaller;
import akka.http.javadsl.model.HttpEntity;
import akka.http.javadsl.model.RequestEntity;
import akka.http.javadsl.unmarshalling.Unmarshaller;

import static org.squbs.marshallers.json.XLangJsonSupport.*;

Marshaller myMarshaller =
    marshaller(MyClass.class);

Unmarshaller myUnmarshaller =
    unmarshaller(MyClass.class);

在本文讨论中,这些解析器和反解析器可以作为 Akka HTTP Routing DSL 的一部分或invoking marshalling/unmarshalling的一部分使用,如下:

下面提供配置XLangJsonSupport的例子:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import org.squbs.marshallers.json.XLangJsonSupport;

/* Global XLangJsonSupport Configuration.
 */

// Adds ParameterNamesModule to Jackson
XLangJsonSupport.setDefaultMapper(
  new ObjectMapper().registerModule(new ParameterNamesModule());
  
// Tells Json4s to use native serialization
XLangJsonSupport.setDefaultSerialization(XLangJsonSupport.nativeSerialization());

// Adds MySerializer and MyOtherSerializer (varargs) to the serializers used by Json4s
XLangJsonSupport.addDefaultSerializers(new MySerializer(), new MyOtherSerializer());


/* Per-class configuration of 'XLangJsonSupport'.
 * In this case we show configuring 'MyClass' and 'MyOtherClass'
 */

// Use ParameterNamesModule for mashal/unmarshal MyClass
XLangJsonSupport.register(MyClass.class, new ParameterNamesModule()));

// Use Json4s Jackson serialization for MyOtherClass
XLangJsonSupport.register(MyOtherClass.class, XLangJsonSupport.jacksonSerialization());

// Adds MySerializer and MyOtherSerializer (varargs) to the serializers used by Json4s for MyOtherClass
XLangJsonSupport.addSerializers(MyOtherClass.class, new MySerializer(), new MyOtherSerializer());

调用序列化/反序列化

除了使用解析器和反解析器作为Akka HTTP Routing DSL的一部分,手动调用序列化/反序列化常常用在服务端和客户端的流和测试中。

Scala

Akka提供 Scala DSL 来实现序列化和反序列化。它的使用例子可以如下所示:

import akka.actor.ActorSystem
import akka.http.scaladsl.marshalling.Marshal
import akka.http.scaladsl.model.MessageEntity
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.stream.ActorMaterializer

// We need the ActorSystem and Materializer to marshal/unmarshal
implicit val system = ActorSystem()
implicit val mat = ActorMaterializer()

// Also need the implicit marshallers provided by this import
import org.squbs.marshallers.json.XLangJsonSupport._

// Just call Marshal or Unmarshal as follows:
Marshal(myObject).to[MessageEntity]
Unmarshal(entity).to[MyType]
Java

用Akka HTTP's JavaDSL中定义的MarshallerUnmarshallerMarshalUnmarshal工具类来手动序列化和反序列化对象。例子如下:

import akka.actor.ActorSystem;
import akka.http.javadsl.model.RequestEntity;
import akka.stream.ActorMaterializer;
import akka.stream.Materializer;

import org.squbs.marshallers.MarshalUnmarshal;

// We're using JacksonMapperSupport here.
// But XLangJsonSupport works the same.
import static org.squbs.marshallers.json.JacksonMapperSupport.*;

// Base infrastructure, and the 'mu' MarshalUnmarshal. 
private final ActorSystem system = ActorSystem.create();
private final Materializer mat = ActorMaterializer.create(system);
private final MarshalUnmarshal mu = new MarshalUnmarshal(system.dispatcher(), mat);

// Call 'apply' passing marshaller or unmarshaller as follows, using marshaller
// and unmarshaller methods from 'import static JacksonMapperSupport.*;':
CompletionStage mf = mu.apply(marshaller(MyClass.class), myObject);
CompletionStage uf = mu.apply(unmarshaller(MyClass.class), entity);

你可能感兴趣的:(squbs-6. 序列化和反序列化)