```xml
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon-serialization-gson</artifactId>
</dependency>
```

#### 1、描述

序列化扩展插件，为 Solon Serialization 提供基于 Gson（[代码仓库](https://github.com/google/gson)）的框架适配。

使用时，会涉及到格式化的定制，其它就不会有显示的感受。


#### 2、主要接口实现类


|  类 | 实现接口 | 备注 |
| -------- | -------- | -------- |
| GsonStringSerializer   | Serializer, EntityStringSerializer      |  json 序列化器（v3.6.0 后为主力）     |
| GsonEntityConverter  | EntityConverter                            | json 实体转换器（v3.6.0 后支持） |
| GsonRenderFactory   | JsonRenderFactory     | 用于处理 json 渲染输出（v3.6.0 后将标为弃用）     |
| GsonActionExecutor  | ActionExecuteHandler | 用于执行 json 内容的请求（v3.6.0 后将标为弃用） |

何时会被时用？当 Content-Type 为 application/json（或 text/json）时会执行。

#### 3、快捷格式化输出配置 (v1.12.3 后支持)

```yml
solon.serialization.json:
  dateAsFormat: 'yyyy-MM-dd HH:mm:ss' #配置日期格式（默认输出为时间戳，对 Date、LocalDateTime 有效）
  dateAsTimeZone: 'GMT+8' #配置时区
  dateAsTicks: false #将date转为毫秒数（和 dateAsFormat 二选一）
  longAsString: true #将long型转为字符串输出 （默认为false）
  boolAsInt: false   #将bool型转为字符串输出 （默认为false）
  nullStringAsEmpty: false
  nullBoolAsFalse: false
  nullNumberAsZero: false
  nullAsWriteable: false #输出所有null值
  enumAsName: false #枚举使用名字（v2.2.1 后支持）
```

提醒：

* 配置 null???As??? 时实体的null字段也会输出（相当于 nullAsWriteable 被动开了）
* nullArrayAsEmpty 不支持


支持过手动获取已配置的序列化接口：

```java
Serializer<String> serializer = Solon.app().serializers().get(SerializerNames.AT_JSON);
Serializer<String> serializer = Solon.context().getBean(GsonStringSerializer.class);
```


#### 4、高级格式化定制（基于接口）


v3.6.0 后，可使用新接口（旧接口，将标为弃用）：

```java
@Configuration
public class DemoConfig {
    @Bean
    public void config(GsonStringSerializer serializer) throws Exception {
        //::序列化（用于渲染输出）
        //示例1：通过转换器，做简单类型的定制（addConvertor 新统一为 addEncoder）
        serializer.addEncoder(Date.class, s -> s.getTime());

        serializer.addEncoder(LocalDate.class, s -> s.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));

        serializer.addEncoder(Long.class, s -> String.valueOf(s));

        //示例2：通过编码器，做复杂类型的原生定制（基于框架原生接口）
        serializer.addEncoder(Date.class, (source, type, jsc) -> {
            return new JsonPrimitive(source.getTime());
        });
        
        //示例3：调整序列化特性
        serializer.getSerializeConfig().getBuilder().serializeNulls();

        //::反序列化（用于接收参数）
        serializer.getDeserializeConfig().getBuilder().serializeNulls();
    }
}
```

格式化输出定制和请求处理定制，（v2.2.5 后支持）：//旧定制接口 v3.6.0 后标为弃用

```java
@Configuration
public class DemoConfig {
    @Bean
    public void config(@Inject GsonRenderFactory factory, @Inject GsonActionExecutor executor){
        //示例1：通过转换器，做简单类型的定制
        factory.addConvertor(Date.class, s -> s.getTime());

        factory.addConvertor(LocalDate.class, s -> s.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));

        factory.addConvertor(Long.class, s -> String.valueOf(s));

        //示例2：通过编码器，做复杂类型的原生定制（基于框架原生接口）
        factory.addEncoder(Date.class, (source, type, jsc) -> {
                    return new JsonPrimitive(source.getTime());
                });
                
        //factory.config()...
        //executor.config()...
    }
}
```


#### 5、个性化输出定制

```java
public class User{
    public long userId;
    
    public String name;
    
    //排除序列化
    public transient password; //使用 transient 排除具有通用性
    
    //格式化日期
    @JsonAdapter(DateFormatAdapter.class) //（DateFormatAdapter 需要自己定义）尽量不使用个性化定制//这样不会依赖具体框架
    public Date birthday;
}
```