实体序列化器 EntitySerializer
前置参考:
1、接口声明
package org.noear.solon.serialization;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.serialize.Serializer;
import org.noear.solon.lang.Nullable;
import java.io.IOException;
import java.lang.reflect.Type;
/**
* 通用实体序列化器(与 EntityConverter 相互对应)
*/
public interface EntitySerializer<T> extends Serializer<T> {
/**
* 匹配
*
* @param ctx 上下文
* @param mime
*/
boolean matched(Context ctx, String mime);
/**
* 媒体类型
*/
String mimeType();
/**
* 必须要 body
*/
default boolean bodyRequired() {
return false;
}
/**
* 序列化到
*
* @param ctx 请求上下文
* @param data 数据
*/
void serializeToBody(Context ctx, Object data) throws IOException;
/**
* 反序列化从
*
* @param ctx 请求上下文
* @param toType 目标类型
* @since 3.0
*/
Object deserializeFromBody(Context ctx, @Nullable Type toType) throws IOException;
/**
* 反序列化从
*
* @param ctx 请求上下文
*/
default Object deserializeFromBody(Context ctx) throws IOException {
return deserializeFromBody(ctx, null);
}
}
扩展接口 EntityStringSerializer :
public interface EntityStringSerializer extends EntitySerializer<String> {
/**
* 添加数据转换器(用于简单场景)
*/
<T> void addEncoder(Class<T> clz, Converter<T, Object> converter);
}
2、定制参考1
package org.noear.solon.serialization.abc;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.ModelAndView;
import org.noear.solon.core.util.ClassUtil;
import org.noear.solon.lang.Nullable;
import org.noear.solon.serialization.EntitySerializer;
import org.noear.solon.serialization.abc.io.AbcSerializable;
import java.io.IOException;
import java.lang.reflect.Type;
public class AbcBytesSerializer implements EntitySerializer<byte[]> {
private static final String label = "application/abc";
private static final AbcBytesSerializer _default = new AbcBytesSerializer();
/**
* 默认实例
*/
public static AbcBytesSerializer getDefault() {
return _default;
}
@Override
public String mimeType() {
return label;
}
@Override
public Class<byte[]> dataType() {
return byte[].class;
}
@Override
public boolean bodyRequired() {
return true;
}
/**
* 序列化器名字
*/
@Override
public String name() {
return "abc-bytes";
}
@Override
public byte[] serialize(Object fromObj) throws IOException {
if (fromObj instanceof AbcSerializable) {
AbcSerializable bs = ((AbcSerializable) fromObj);
Object out = bs.serializeFactory().createOutput();
bs.serializeWrite(out);
return bs.serializeFactory().extractBytes(out);
} else {
throw new IllegalStateException("The parameter 'fromObj' is not of AbcSerializable");
}
}
@Override
public Object deserialize(byte[] data, Type toType) throws IOException {
if (toType instanceof Class<?>) {
if (AbcSerializable.class.isAssignableFrom((Class<?>) toType)) {
AbcSerializable tmp = ClassUtil.newInstance((Class<?>) toType);
Object in = tmp.serializeFactory().createInput(data);
tmp.serializeRead(in);
return tmp;
} else {
throw new IllegalStateException("The parameter 'toType' is not of AbcSerializable");
}
} else {
throw new IllegalStateException("The parameter 'toType' is not Class");
}
}
/// ////////////
@Override
public boolean matched(Context ctx, String mime) {
if (mime == null) {
return false;
} else {
return mime.startsWith(label);
}
}
@Override
public void serializeToBody(Context ctx, Object data) throws IOException {
//如果没有设置过,用默认的 //如 ndjson,sse 或故意改变 mime(可由外部控制)
if (ctx.contentTypeNew() == null) {
ctx.contentType(this.mimeType());
}
if (data instanceof ModelAndView) {
ctx.output(serialize(((ModelAndView) data).model()));
} else {
ctx.output(serialize(data));
}
}
@Override
public Object deserializeFromBody(Context ctx, @Nullable Type bodyType) throws IOException {
return deserialize(ctx.bodyAsBytes(), bodyType);
}
}
3、定制参考2
package org.noear.solon.serialization.fastjson2;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.reader.ObjectReaderProvider;
import com.alibaba.fastjson2.writer.ObjectWriter;
import com.alibaba.fastjson2.writer.ObjectWriterProvider;
import org.noear.solon.Utils;
import org.noear.solon.core.convert.Converter;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.ModelAndView;
import org.noear.solon.core.util.MimeType;
import org.noear.solon.lang.Nullable;
import org.noear.solon.serialization.EntityStringSerializer;
import org.noear.solon.serialization.prop.JsonProps;
import org.noear.solon.serialization.prop.JsonPropsUtil2;
import java.io.IOException;
import java.lang.reflect.Type;
/**
* Fastjson2 字符串序列化
*/
public class Fastjson2StringSerializer implements EntityStringSerializer {
private static final String label = "/json";
private static final Fastjson2StringSerializer _default = new Fastjson2StringSerializer();
/**
* 默认实例
*/
public static Fastjson2StringSerializer getDefault() {
return _default;
}
private Fastjson2Decl<JSONWriter.Context, JSONWriter.Feature> serializeConfig;
private Fastjson2Decl<JSONReader.Context, JSONReader.Feature> deserializeConfig;
public Fastjson2StringSerializer(JsonProps jsonProps) {
loadJsonProps(jsonProps);
}
public Fastjson2StringSerializer() {
}
/**
* 获取序列化配置
*/
public Fastjson2Decl<JSONWriter.Context, JSONWriter.Feature> getSerializeConfig() {
if (serializeConfig == null) {
serializeConfig = new Fastjson2Decl<>(new JSONWriter.Context(new ObjectWriterProvider()));
}
return serializeConfig;
}
/**
* 获取反序列化配置
*/
public Fastjson2Decl<JSONReader.Context, JSONReader.Feature> getDeserializeConfig() {
if (deserializeConfig == null) {
deserializeConfig = new Fastjson2Decl<>(new JSONReader.Context(new ObjectReaderProvider()));
}
return deserializeConfig;
}
/**
* 内容类型
*/
@Override
public String mimeType() {
return "application/json";
}
/**
* 数据类型
*
*/
@Override
public Class<String> dataType() {
return String.class;
}
/**
* 是否匹配
*
* @param ctx 请求上下文
* @param mime 内容类型
*/
@Override
public boolean matched(Context ctx, String mime) {
if (mime == null) {
return false;
} else {
return mime.contains(label) || mime.startsWith(MimeType.APPLICATION_X_NDJSON_VALUE);
}
}
/**
* 序列化器名字
*/
@Override
public String name() {
return "fastjson2-json";
}
/**
* 序列化
*
* @param obj 对象
*/
@Override
public String serialize(Object obj) throws IOException {
return JSON.toJSONString(obj, getSerializeConfig().getContext());
}
/**
* 反序列化
*
* @param data 数据
* @param toType 目标类型
*/
@Override
public Object deserialize(String data, Type toType) throws IOException {
if (toType == null) {
return JSON.parse(data, getDeserializeConfig().getContext());
} else {
return JSON.parseObject(data, toType, getDeserializeConfig().getContext());
}
}
/**
* 序列化主体
*
* @param ctx 请求上下文
* @param data 数据
*/
@Override
public void serializeToBody(Context ctx, Object data) throws IOException {
//如果没有设置过,用默认的 //如 ndjson,sse 或故意改变 mime(可由外部控制)
if (ctx.contentTypeNew() == null) {
ctx.contentType(this.mimeType());
}
if (data instanceof ModelAndView) {
ctx.output(serialize(((ModelAndView) data).model()));
} else {
ctx.output(serialize(data));
}
}
/**
* 反序列化主体
*
* @param ctx 请求上下文
*/
@Override
public Object deserializeFromBody(Context ctx, @Nullable Type bodyType) throws IOException {
String data = ctx.bodyNew();
if (Utils.isNotEmpty(data)) {
return JSON.parse(data, getDeserializeConfig().getContext());
} else {
return null;
}
}
/**
* 添加编码器
*
* @param clz 类型
* @param encoder 编码器
*/
public <T> void addEncoder(Class<T> clz, ObjectWriter encoder) {
getSerializeConfig().getContext().getProvider().register(clz, encoder);
}
/**
* 添加转换器(编码器的简化版)
*
* @param clz 类型
* @param converter 转换器
*/
@Override
public <T> void addEncoder(Class<T> clz, Converter<T, Object> converter) {
addEncoder(clz, (out, obj, fieldName, fieldType, features) -> {
Object val = converter.convert((T) obj);
if (val == null) {
out.writeNull();
} else if (val instanceof String) {
out.writeString((String) val);
} else if (val instanceof Number) {
if (val instanceof Long) {
out.writeInt64(((Number) val).longValue());
} else if (val instanceof Integer) {
out.writeInt32(((Number) val).intValue());
} else if (val instanceof Float) {
out.writeDouble(((Number) val).floatValue());
} else {
out.writeDouble(((Number) val).doubleValue());
}
} else {
throw new IllegalArgumentException("The result type of the converter is not supported: " + val.getClass().getName());
}
});
}
protected void loadJsonProps(JsonProps jsonProps) {
if (jsonProps != null) {
if (jsonProps.dateAsTicks) {
jsonProps.dateAsTicks = false;
getSerializeConfig().getContext().setDateFormat("millis");
}
if (Utils.isNotEmpty(jsonProps.dateAsFormat)) {
//这个方案,可以支持全局配置,且个性注解不会失效;//用编码器会让个性注解失效
getSerializeConfig().getContext().setDateFormat(jsonProps.dateAsFormat);
}
//JsonPropsUtil.dateAsFormat(this, jsonProps);
JsonPropsUtil2.dateAsTicks(this, jsonProps);
JsonPropsUtil2.boolAsInt(this, jsonProps);
boolean writeNulls = jsonProps.nullAsWriteable ||
jsonProps.nullNumberAsZero ||
jsonProps.nullArrayAsEmpty ||
jsonProps.nullBoolAsFalse ||
jsonProps.nullStringAsEmpty;
if (jsonProps.nullStringAsEmpty) {
getSerializeConfig().addFeatures(JSONWriter.Feature.WriteNullStringAsEmpty);
}
if (jsonProps.nullBoolAsFalse) {
getSerializeConfig().addFeatures(JSONWriter.Feature.WriteNullBooleanAsFalse);
}
if (jsonProps.nullNumberAsZero) {
getSerializeConfig().addFeatures(JSONWriter.Feature.WriteNullNumberAsZero);
}
if (jsonProps.boolAsInt) {
getSerializeConfig().addFeatures(JSONWriter.Feature.WriteBooleanAsNumber);
}
if (jsonProps.longAsString) {
getSerializeConfig().addFeatures(JSONWriter.Feature.WriteLongAsString);
}
if (jsonProps.nullArrayAsEmpty) {
getSerializeConfig().addFeatures(JSONWriter.Feature.WriteNullListAsEmpty);
}
if (jsonProps.enumAsName) {
getSerializeConfig().addFeatures(JSONWriter.Feature.WriteEnumsUsingName);
}
if (writeNulls) {
getSerializeConfig().addFeatures(JSONWriter.Feature.WriteNulls);
}
}
}
}