@@ -1,2 +1,395 @@
# Json 序列化
文档完善中……
# 序列化
   Convert提供Java对象的序列化与反序列化功能。支持JSON(JavaScript Object Notation)、BSON(Binary Stream Object Notation)、PROTOBUF三种格式化。 三种格式使用方式完全一样, 其性能都大幅度超过其他JSON框架。同时JSON内置于HTTP服务中, BSON也是SNCP协议数据序列化的基础。
## 基本API
   JSON序列化其操作类主要是JsonConvert, 配置类主要是JsonFactory、ConvertColumn。JsonFactory采用同ClassLoader类似的双亲委托方式设计。
JsonConvert 序列化encode方法:
```java
public String convertTo ( Object value );
public String convertTo ( Type type , Object value );
public void convertTo ( OutputStream out , Object value );
public void convertTo ( OutputStream out , Type type , Object value );
public ByteBuffer [] convertTo ( Supplier < ByteBuffer > supplier , Object value );
public ByteBuffer [] convertTo ( Supplier < ByteBuffer > supplier , Type type , Object value );
public void convertTo ( JsonWriter writer , Object value );
public void convertTo ( JsonWriter writer , Type type , Object value );
```
JsonConvert 反序列化decode方法:
```java
public < T > T convertFrom ( Type type , String text );
public < T > T convertFrom ( Type type , char [] text );
public < T > T convertFrom ( Type type , char [] text , int start , int len );
public < T > T convertFrom ( Type type , InputStream in );
public < T > T convertFrom ( Type type , ByteBuffer ... buffers );
public < T > T convertFrom ( Type type , JsonReader reader );
```
## Json基本用法
```java
@Data
public class UserRecord {
private int userid ;
private String username = "" ;
private String password = "" ;
public UserRecord () {
}
}
public static void main ( String [] args ) throws Exception {
UserRecord user = new UserRecord ();
user . setUserid ( 100 );
user . setUsername ( "redkalename" );
user . setPassword ( "123456" );
final JsonConvert convert = JsonConvert . root ();
String json = convert . convertTo ( user );
System . out . println ( json ); //应该是 {"password":"123456","userid":100,"username":"redkalename"}
UserRecord user2 = convert . convertFrom ( UserRecord . class , json );
System . out . println ( convert . convertTo ( user2 )); //应该也是 {"password":"123456","userid":100,"username":"redkalename"}
/**
* 以下功能是为了屏蔽password字段。
* 等价于 public String getPassword() 加上 @ConvertColumn :
*
* @ConvertColumn(ignore = true, type = ConvertType.JSON)
* public String getPassword() {
* return password;
* }
**/
final JsonFactory childFactory = JsonFactory . root (). createChild ();
childFactory . register ( UserRecord . class , true , "password" ); //屏蔽掉password字段使其不输出
childFactory . reloadCoder ( UserRecord . class ); //重新加载Coder使之覆盖父Factory的配置
final JsonConvert childConvert = childFactory . getConvert ();
json = childConvert . convertTo ( user );
System . out . println ( json ); //应该是 {"userid":100,"username":"redkalename"}
user2 = childConvert . convertFrom ( UserRecord . class , json );
System . out . println ( childConvert . convertTo ( user2 )); //应该也是 {"userid":100,"username":"redkalename"}
}
```
   在Redkale里存在默认的JsonConvert、BsonConvert、ProtobufConvert对象。 只需在所有Service、Servlet中增加依赖注入资源。
```java
public class XXXService implements Service {
@Resource
private JsonConvert jsonConvert ;
@Resource
private BsonConvert bsonConvert ;
@Resource
private ProtobufConvert protobufConvert ;
}
public class XXXServlet extends HttpServlet {
@Resource
private JsonConvert jsonConvert ;
@Resource
private BsonConvert bsonConvert ;
@Resource
private ProtobufConvert protobufConvert ;
}
```
   同一类型数据通过设置新的JsonFactory可以有不同的输出。
```java
public class UserSimpleInfo {
private int userid ;
private String username = "" ;
@ConvertColumn ( ignore = true , type = ConvertType . JSON )
private long regtime ; //注册时间
@ConvertColumn ( ignore = true , type = ConvertType . JSON )
private String regaddr = "" ; //注册IP
/** 以下省略getter setter方法 */
}
public class UserInfoServlet extends HttpBaseServlet {
@Resource
private UserSerice service ;
@Resource
private JsonFactory jsonRootFactory ;
@Resource
private JsonConvert detailConvert ;
@Override
public void init ( HttpContext context , AnyValue config ) {
final JsonFactory childFactory = jsonRootFactory . createChild ();
childFactory . register ( UserSimpleInfo . class , false , "regtime" , "regaddr" ); //允许输出注册时间与注册地址
childFactory . reloadCoder ( UserSimpleInfo . class ); //重新加载Coder使之覆盖父Factory的配置
this . detailConvert = childFactory . getConvert ();
}
// 获取他人基本信息
@HttpMapping ( url = "/user/info/" )
public void info ( HttpRequest req , HttpResponse resp ) throws IOException {
int userid = Integer . parseInt ( req . getRequstURILastPath ());
UserSimpleInfo user = service . findUserInfo ( userid );
resp . finishJson ( user ); // 不包含用户的注册时间和注册地址字段信息
}
//获取用户自己的信息
@HttpMapping ( url = "/user/myinfo" )
public void mydetail ( HttpRequest req , HttpResponse resp ) throws IOException {
int userid = req . currentUser (). getUserid (); //获取当前用户ID
UserSimpleInfo user = service . findUserInfo ( userid );
resp . finishJson ( detailConvert , user ); // 包含用户的注册时间和注册地址字段信息
}
}
```
   Convert 支持带参数构造函数。
1. public 带参数的构造函数加上 @ConstructorParameters 注解:
```java
public class UserRecord {
private int userid ;
private String username = "" ;
private String password = "" ;
@ConstructorParameters ({ "userid" , "username" , "password" })
public UserRecord ( int userid , String username , String password ) {
this . userid = userid ;
this . username = username ;
this . password = password ;
}
public int getUserid () {
return userid ;
}
public String getUsername () {
return username ;
}
public String getPassword () {
return password ;
}
}
```
2. 自定义Creator:
```java
public class UserRecord {
private int userid ;
private String username = "" ;
private String password = "" ;
UserRecord ( int userid , String username , String password ) {
this . userid = userid ;
this . username = username ;
this . password = password ;
}
public int getUserid () {
return userid ;
}
public String getUsername () {
return username ;
}
public String getPassword () {
return password ;
}
/**
* 自定义Creator方法。
* 1) 方法名可以随意。
* 2) 方法必须是static。
* 3) 方法的参数必须为空。
* 4) 方法的返回类型必须是Creator。
*
* @return
*/
private static Creator < UserRecord > creator () {
return new Creator < UserRecord > () {
@Override
@ConstructorParameters ({ "userid" , "username" , "password" }) //带参数的构造函数必须有ConstructorParameters注解
public UserRecord create ( Object ... params ) {
return new UserRecord (( params [ 0 ] == null ? 0 : ( Integer ) params [ 0 ] ), ( String ) params [ 1 ] , ( String ) params [ 2 ] );
}
};
}
}
```
   通常JavaBean类默认有个public空参数的构造函数, 因此大部分情况下不要自定义Creator, 其实只要不是private的空参数构造函数Convert都能自动支持(其他的框架都仅支持public的构造函数), 只有仅含private的构造函数才需要自定义Creator。带参数的构造函数就需要标记@ConstructorParameters , 常见于Immutable Object。
## 自定义
   Convert 支持自定义Decode、Encode。
1. 通过ConvertFactory显式的注册:
```java
public class FileSimpleCoder < R extends Reader , W extends Writer > extends SimpledCoder < R , W , File > {
public static final FileSimpleCoder instance = new FileSimpleCoder ();
@Override
public void convertTo ( W out , File value ) {
out . writeString ( value == null ? null : value . getPath ());
}
@Override
public File convertFrom ( R in ) {
String path = in . readString ();
return path == null ? null : new File ( path );
}
}
JsonFactory . root (). register ( File . class , FileSimpleCoder . instance );
BsonFactory . root (). register ( File . class , FileSimpleCoder . instance );
```
2. 通过JavaBean类自定义静态方法自动加载:
```java
public class InnerCoderEntity {
private final String val ;
private final int id ;
private InnerCoderEntity ( int id , String value ) {
this . id = id ;
this . val = value ;
}
public static InnerCoderEntity create ( int id , String value ) {
return new InnerCoderEntity ( id , value );
}
/**
* 该方法提供给Convert组件自动加载。
* 1) 方法名可以随意。
* 2) 方法必须是static
* 3) 方法的参数有且只能有一个, 且必须是org.redkale.convert.ConvertFactory或子类。
* —3.1) 参数类型为org.redkale.convert.ConvertFactory 表示适合JSON和BSON。
* —3.2) 参数类型为org.redkale.convert.json.JsonFactory 表示仅适合JSON。
* —3.3) 参数类型为org.redkale.convert.bson.BsonFactory 表示仅适合BSON。
* 4) 方法的返回类型必须是org.redkale.convert.Decodeable/org.redkale.convert.Encodeable/org.redkale.convert.SimpledCoder
* 若返回类型不是org.redkale.convert.SimpledCoder, 就必须提供两个方法: 一个返回Decodeable 一个返回 Encodeable。
*
* @param factory
* @return
*/
private static SimpledCoder < Reader , Writer , InnerCoderEntity > createConvertCoder ( final org . redkale . convert . ConvertFactory factory ) {
return new SimpledCoder < Reader , Writer , InnerCoderEntity > () {
//必须与EnMember[] 顺序一致
private final DeMember [] deMembers = new DeMember [] {
DeMember . create ( factory , InnerCoderEntity . class , "id" ),
DeMember . create ( factory , InnerCoderEntity . class , "val" )};
//必须与DeMember[] 顺序一致
private final EnMember [] enMembers = new EnMember [] {
EnMember . create ( factory , InnerCoderEntity . class , "id" ),
EnMember . create ( factory , InnerCoderEntity . class , "val" )};
@Override
public void convertTo ( Writer out , InnerCoderEntity value ) {
if ( value == null ) {
out . writeObjectNull ( InnerCoderEntity . class );
return ;
}
out . writeObjectB ( value );
for ( EnMember member : enMembers ) {
out . writeObjectField ( member , value );
}
out . writeObjectE ( value );
}
@Override
public InnerCoderEntity convertFrom ( Reader in ) {
if ( in . readObjectB ( InnerCoderEntity . class ) == null ) return null ;
int index = 0 ;
final Object [] params = new Object [ deMembers . length ] ;
while ( in . hasNext ()) {
DeMember member = in . readFieldName ( deMembers ); //读取字段名
in . readBlank (); //读取字段名与字段值之间的间隔符, JSON则是跳过冒号:
if ( member == null ) {
in . skipValue (); //跳过不存在的字段的值, 一般不会发生
} else {
params [ index ++] = member . read ( in );
}
}
in . readObjectE ( InnerCoderEntity . class );
return InnerCoderEntity . create ( params [ 0 ] == null ? 0 : ( Integer ) params [ 0 ] , ( String ) params [ 1 ] );
}
};
}
public int getId () {
return id ;
}
public String getVal () {
return val ;
}
@Override
public String toString () {
return JsonConvert . root (). convertTo ( this );
}
}
```
## Bson数据格式
   BSON类似Java自带的Serializable, 其格式如下:
     1). 基本数据类型: 直接转换成byte[]
     2). SmallString(无特殊字符且长度小于256的字符串): length(1 byte) + byte[](utf8); 通常用于类名、字段名、枚举。
     3). String: length(4 bytes) + byte[](utf8);
     4). 数组: length(4 bytes) + byte[]...
     5). Object:
       1. realclass (SmallString) (如果指定格式化的class与实体对象的class不一致才会有该值, 该值可以使用@ConvertEntity给其取个别名 )
       2. 空字符串(SmallString)
       3. SIGN_OBJECTB 标记位, 值固定为0xBB (short)
       4. 循环字段值:
         4.1 SIGN_HASNEXT 标记位, 值固定为1 (byte)
         4.2 字段类型; 1-9为基本类型&字符串; 101-109为基本类型&字符串的数组; 127为Object
         4.3 字段名 (SmallString)
         4.4 字段的值Object
       5. SIGN_NONEXT 标记位, 值固定为0 (byte)
       6. SIGN_OBJECTE 标记位, 值固定为0xEE (short)