Solon v3.6.2

实体转换器 EntityConverter

</> markdown

1、接口声明

package org.noear.solon.core.handle;

import org.noear.solon.core.wrap.MethodWrap;
import org.noear.solon.lang.Preview;

/**
 * 实体转换器(预览,未启用)
 */
public interface EntityConverter {
    /**
     * 实例检测(移除时用)
     */
    default boolean isInstance(Class<?> clz) {
        return clz.isInstance(this);
    }

    /**
     * 名字
     */
    default String name() {
        return this.getClass().getSimpleName();
    }

    /**
     * 映射
     */
    default String[] mappings() {
        return null;
    }

    /**
     * 是否允许写
     *
     */
    boolean allowWrite();

    /**
     * 是否能写
     */
    boolean canWrite(String mime, Context ctx);

    /**
     * 写入并返回(渲染并返回(默认不实现))
     */
    String writeAndReturn(Object data, Context ctx) throws Throwable;

    /**
     * 写入
     *
     * @param data 数据
     * @param ctx  上下文
     */
    void write(Object data, Context ctx) throws Throwable;

    /**
     * 是否允许读
     */
    boolean allowRead();

    /**
     * 是否能读
     */
    boolean canRead(Context ctx, String mime);

    /**
     * 读取(参数分析)
     *
     * @param ctx    上下文
     * @param target 控制器
     * @param mWrap  函数包装器
     */
    Object[] read(Context ctx, Object target, MethodWrap mWrap) throws Throwable;
}

扩展虚拟类 AbstractEntityConverter:

public abstract class AbstractEntityConverter extends AbstractEntityReader implements EntityConverter {
    @Override
    public Object[] read(Context ctx, Object target, MethodWrap mWrap) throws Throwable {
        return doRead(ctx, target, mWrap);
    }
}

扩展虚拟类 AbstractBytesEntityConverter:

package org.noear.solon.serialization;

import org.noear.solon.core.handle.AbstractEntityConverter;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.util.Assert;

import java.util.Base64;

/**
 * 虚拟字节码实体转换器
 */
public abstract class AbstractBytesEntityConverter<T extends EntitySerializer<byte[]>> extends AbstractEntityConverter {
    protected final T serializer;

    public T getSerializer() {
        return serializer;
    }

    public AbstractBytesEntityConverter(T serializer) {
        Assert.notNull(serializer, "Serializer not be null");
        this.serializer = serializer;
    }

    @Override
    public boolean allowWrite() {
        return true;
    }

    @Override
    public boolean canWrite(String mime, Context ctx) {
        return serializer.matched(ctx, mime);
    }

    @Override
    public String writeAndReturn(Object data, Context ctx) throws Throwable {
        byte[] tmp = serializer.serialize(data);
        return Base64.getEncoder().encodeToString(tmp);
    }

    @Override
    public void write(Object data, Context ctx) throws Throwable {
        if (SerializationConfig.isOutputMeta()) {
            ctx.headerAdd("solon.serialization", name());
        }

        serializer.serializeToBody(ctx, data);
    }

    @Override
    public boolean allowRead() {
        return true;
    }

    @Override
    public boolean canRead(Context ctx, String mime) {
        return serializer.matched(ctx, mime);
    }
}

扩展虚拟类 AbstractStringEntityConverter :

package org.noear.solon.serialization;

import org.noear.solon.core.handle.AbstractEntityConverter;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.util.Assert;

/**
 * 虚拟字符串实体转换器
 */
public abstract class AbstractStringEntityConverter<T extends EntitySerializer<String>> extends AbstractEntityConverter {
    protected final T serializer;

    public T getSerializer() {
        return serializer;
    }

    public AbstractStringEntityConverter(T serializer) {
        Assert.notNull(serializer, "Serializer not be null");
        this.serializer = serializer;
    }

    protected boolean isWriteType() {
        return false;
    }

    @Override
    public boolean allowWrite() {
        return true;
    }

    @Override
    public boolean canWrite(String mime, Context ctx) {
        return serializer.matched(ctx, mime);
    }

    @Override
    public String writeAndReturn(Object data, Context ctx) throws Throwable {
        return serializer.serialize(data);
    }

    @Override
    public void write(Object data, Context ctx) throws Throwable {
        if (SerializationConfig.isOutputMeta()) {
            ctx.headerAdd("solon.serialization", name());
        }

        String text = null;

        if (isWriteType()) {
            //序列化处理
            //
            text = serializer.serialize(data);
        } else {
            //非序列化处理
            //
            if (data == null) {
                return;
            }

            if (data instanceof Throwable) {
                throw (Throwable) data;
            }

            text = serializer.serialize(data);
        }

        ctx.attrSet("output", text);

        doWrite(ctx, data, text);
    }

    /**
     * 输出
     *
     * @param ctx  上下文
     * @param data 数据(原)
     * @param text 文源
     */
    protected void doWrite(Context ctx, Object data, String text) {
        if (data instanceof String && isWriteType() == false) {
            ctx.output(text);
        } else {
            //如果没有设置过,用默认的 //如 ndjson,sse 或故意改变 mime(可由外部控制)
            if (ctx.contentTypeNew() == null) {
                ctx.contentType(serializer.mimeType());
            }

            ctx.output(text);
        }
    }

    @Override
    public boolean allowRead() {
        return true;
    }

    @Override
    public boolean canRead(Context ctx, String mime) {
        return serializer.matched(ctx, mime);
    }
}

2、定制参考1

package org.noear.solon.serialization.abc;

import org.noear.solon.core.handle.Context;
import org.noear.solon.core.util.LazyReference;
import org.noear.solon.core.wrap.MethodWrap;
import org.noear.solon.core.wrap.ParamWrap;
import org.noear.solon.serialization.AbstractBytesEntityConverter;
import org.noear.solon.serialization.SerializerNames;

/**
 * Abc 实体转换器
 */
public class AbcEntityConverter extends AbstractBytesEntityConverter<AbcBytesSerializer> {

    public AbcEntityConverter(AbcBytesSerializer serializer) {
        super(serializer);
    }

    /**
     * 后缀或名字映射
     */
    @Override
    public String[] mappings() {
        return new String[]{SerializerNames.AT_ABC};
    }

    /**
     * 转换 body
     *
     * @param ctx   请求上下文
     * @param mWrap 函数包装器
     */
    @Override
    protected Object changeBody(Context ctx, MethodWrap mWrap) throws Exception {
        return null;
    }

    /**
     * 转换 value
     *
     * @param ctx     请求上下文
     * @param p       参数包装器
     * @param pi      参数序位
     * @param pt      参数类型
     * @param bodyRef 主体对象
     */
    @Override
    protected Object changeValue(Context ctx, ParamWrap p, int pi, Class<?> pt, LazyReference bodyRef) throws Throwable {
        if (p.spec().isRequiredPath() || p.spec().isRequiredCookie() || p.spec().isRequiredHeader()) {
            //如果是 path、cookie, header
            return super.changeValue(ctx, p, pi, pt, bodyRef);
        }

        if (p.spec().isRequiredBody() == false && ctx.paramMap().containsKey(p.spec().getName())) {
            //有可能是path、queryString变量
            return super.changeValue(ctx, p, pi, pt, bodyRef);
        }

        if (p.spec().isRequiredBody()) {
            return serializer.deserializeFromBody(ctx, p.getType());
        } else {
            return null;
        }
    }
}

3、定制参考1

package org.noear.solon.serialization.fastjson2;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.util.LazyReference;
import org.noear.solon.core.wrap.MethodWrap;
import org.noear.solon.core.wrap.ParamWrap;
import org.noear.solon.serialization.AbstractStringEntityConverter;
import org.noear.solon.serialization.SerializerNames;

import java.util.Collection;
import java.util.List;

/**
 * Fastjson2 实体转换器
 */
public class Fastjson2EntityConverter extends AbstractStringEntityConverter<Fastjson2StringSerializer> {
    public Fastjson2EntityConverter(Fastjson2StringSerializer serializer) {
        super(serializer);

        serializer.getDeserializeConfig().addFeatures(JSONReader.Feature.ErrorOnEnumNotMatch);
        serializer.getSerializeConfig().addFeatures(JSONWriter.Feature.BrowserCompatible);
    }

    /**
     * 后缀或名字映射
     */
    @Override
    public String[] mappings() {
        return new String[]{SerializerNames.AT_JSON};
    }

    /**
     * 转换 body
     *
     * @param ctx   请求上下文
     * @param mWrap 函数包装器
     */
    @Override
    protected Object changeBody(Context ctx, MethodWrap mWrap) throws Exception {
        return serializer.deserializeFromBody(ctx);
    }

    /**
     * 转换 value
     *
     * @param ctx     请求上下文
     * @param p       参数包装器
     * @param pi      参数序位
     * @param pt      参数类型
     * @param bodyRef 主体对象
     */
    @Override
    protected Object changeValue(Context ctx, ParamWrap p, int pi, Class<?> pt, LazyReference bodyRef) throws Throwable {
        if (p.spec().isRequiredPath() || p.spec().isRequiredCookie() || p.spec().isRequiredHeader()) {
            //如果是 path、cookie, header 变量
            return super.changeValue(ctx, p, pi, pt, bodyRef);
        }

        if (p.spec().isRequiredBody() == false && ctx.paramMap().containsKey(p.spec().getName())) {
            //可能是 path、queryString 变量
            return super.changeValue(ctx, p, pi, pt, bodyRef);
        }

        Object bodyObj = bodyRef.get();

        if (bodyObj == null) {
            return super.changeValue(ctx, p, pi, pt, bodyRef);
        }

        if (bodyObj instanceof JSONObject) {
            JSONObject tmp = (JSONObject) bodyObj;

            if (p.spec().isRequiredBody() == false) {
                //
                //如果没有 body 要求;尝试找按属性找
                //
                if (tmp.containsKey(p.spec().getName())) {
                    //支持泛型的转换
                    if (p.spec().isGenericType()) {
                        return tmp.getObject(p.spec().getName(), p.getGenericType());
                    } else {
                        return tmp.getObject(p.spec().getName(), pt);
                    }
                }
            }

            //尝试 body 转换
            if (pt.isPrimitive() || pt.getTypeName().startsWith("java.lang.")) {
                return super.changeValue(ctx, p, pi, pt, bodyRef);
            } else {
                if (List.class.isAssignableFrom(pt)) {
                    return null;
                }

                if (pt.isArray()) {
                    return null;
                }

                //支持泛型的转换 如:Map<T>
                if (p.spec().isGenericType()) {
                    return tmp.to(p.getGenericType());
                } else {
                    return tmp.to(pt);
                }
            }
        }

        if (bodyObj instanceof JSONArray) {
            JSONArray tmp = (JSONArray) bodyObj;
            //如果参数是非集合类型
            if (!Collection.class.isAssignableFrom(pt)) {
                return null;
            }
            //集合类型转换
            if (p.spec().isGenericType()) {
                //转换带泛型的集合
                return tmp.to(p.getGenericType());
            } else {
                //不仅可以转换为List 还可以转换成Set
                return tmp.to(pt);
            }
        }

        return bodyObj;
    }
}