fastjson:实现对java.nio.ByteBuffer数据类型的支持

一般情况下,我们都用byte[]作为保存二进制数据的数据类型,较少用ByteBuffer来表示字节数组。然而最近的工作中需要二进制数据(字节数组)即支持fastjson序列化也要能用thrift:swift序列化。 我们知道fastjson可以对byte[]进行序列化,但fastjson默认是不支持java.noi.ByteBuffer数据类型序列化的。 而thrift是跨语言的,所以它并没有byte[]这样的类型,对于二进制数据则对应的用binary类型,在java对应的是java.nio.ByteBuffer。这就尴尬了。

那么到底字节数组用什么表示?byte[] or ByteBuffer?

看来还是得用ByteBuffer,因为fastjson是个非常灵活的框架,允许使用者通过自定义对象实现对特定类型的序列化支持,只要fastjson能支持ByteBuffer的序列化,thrift也就没问题了。 如果想要实现对ByteBuffer类型的支持,需要自己实现ByteBuffer的序列化器和反序列化器(ObjectSerializer, ObjectDeserializer),以下是代码实现。 ByteBufferCodec.java

package gu.simplemq.json;

import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.ByteBuffer;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.PrimitiveArraySerializer;
import com.alibaba.fastjson.serializer.SerializerFeature;

/**
 * {@link ByteBuffer} 序列化反序列化支持
 * @author guyadong
 *
 */
public class ByteBufferCodec implements ObjectSerializer, ObjectDeserializer {
    public static ByteBufferCodec instance = new ByteBufferCodec();
    @SuppressWarnings("unchecked")
    @Override
    public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
        int token = parser.lexer.token();
        if (token == JSONToken.NULL) {
            parser.lexer.nextToken();
            return null;
        } else if(token == JSONToken.HEX  || token == JSONToken.LITERAL_STRING){
            byte[] bytes = parser.lexer.bytesValue();
            parser.lexer.nextToken();
            return (T) ByteBuffer.wrap(bytes);
        }
        throw new JSONException(String.format("invalid '%s' for ByteBuffer",JSONToken.name(token)));
    }

    @Override
    public int getFastMatchToken() {
        return JSONToken.LITERAL_STRING;
    }
    /**
     * 返回buffer中所有字节(position~limit),不改变buffer状态
     * @param buffer
     * @return
     */
    private static final byte[] getAllBytesInBuffer(ByteBuffer buffer){
        int pos = buffer.position();
        try{
            byte[] bytes = new byte[buffer.remaining()];
            buffer.get(bytes);
            return bytes;
        }finally{
            buffer.position(pos);
        }
    }
    /** 
     * 直接引用{@link PrimitiveArraySerializer}实现序列化
     */
    @Override
    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features)
            throws IOException {
        if ( (object instanceof ByteBuffer) ) {
            PrimitiveArraySerializer.instance.write(serializer, getAllBytesInBuffer((ByteBuffer)object), fieldName, fieldType, features);
        }else{
            serializer.out.writeNull(SerializerFeature.WriteNullListAsEmpty);
        }

    }
}

使用示例:

package gu.simplemq;

import java.nio.ByteBuffer;

import org.junit.Test;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializeConfig;

import gu.simplemq.json.ByteBufferCodec;

public class TestByteBuffer {

    @Test
    public void test() {
        ByteBuffer byteBuffer =ByteBuffer.wrap(new byte[]{22,33,3,2,3,1,5,-1});
        // 修改ParserConfig.global全局变量,将ByteBufferCodec加入反序列化器容器
        ParserConfig.global.putDeserializer(ByteBuffer.class, ByteBufferCodec.instance);
        // 修改SerializeConfig.globalInstance全局变量,将ByteBufferCodec加入序列化器容器
        // 对应的Class为 java.nio.HeapByteBuffer
        SerializeConfig.globalInstance.put(ByteBuffer.wrap(new byte[]{}).getClass(), ByteBufferCodec.instance);
        // 待序列化的 ByteBuffer 对象
        ByteBuffer byteBuffer =ByteBuffer.wrap(new byte[]{22,33,3,2,3,1,5,-1});
        // 序列化
        String serString = JSON.toJSONString(group.byteBuffer);
        System.out.println(serString);
        // 反序列化
        ByteBuffer deserialedByteBuffer = JSON.parseObject(serString,ByteBuffer.class);
        System.out.println(JSON.toJSONString(deserialedByteBuffer));
    }

}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏二进制文集

FastJSON 源码分析

Fastjson是一个Java语言编写的高性能功能完善的JSON库。它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致,是目前Java...

942
来自专栏Keegan小钢

Android项目重构之路:实现篇(二)

核心层处于接口层和界面层之间,向下调用Api,向上提供Action,它的核心任务就是处理复杂的业务逻辑。先看看我对Action的定义:

812
来自专栏WindCoder

个人常用语句笔记-Java

JDK1.7的新语法,这种try语句可以自动执行资源关闭过程,无需再在finally中显式关闭流。

591
来自专栏青枫的专栏

day34_Spring学习笔记_02

1.2.2.2、切面类   MyAspect.java的代码同上 1.2.1.2、切面类 代码,这里不再赘述!

594
来自专栏软件开发

MyBatis学习总结(二)——MyBatis核心配置文件与输入输出映射

在上一章中我们学习了《MyBatis学习总结(一)——ORM概要与MyBatis快速起步》,这一章主要是介绍MyBatis核心配置文件、使用接口+XML实现完整...

592
来自专栏软件开发

MyBatis学习总结(二)——MyBatis核心配置文件与输入输出映射

在上一章中我们学习了《MyBatis学习总结(一)——ORM概要与MyBatis快速起步》,这一章主要是介绍MyBatis核心配置文件、使用接口+XML实现完整...

513
来自专栏Hongten

spring开发_AOP_代理模式

http://www.cnblogs.com/hongten/gallery/image/112445.html

682
来自专栏ASP.NET MVC5 后台权限管理系统

ASP.NET MVC5+EF6+EasyUI 后台管理系统(17)-LinQ动态排序

首先修复程序中的一个BUG这个BUG在GridPager类中,把sord修改为sort这个名称填写错误,会导致后台一直无法获取datagrid的排序字段 本来是...

1995
来自专栏Java3y

JSON就是这么简单

什么是JSON JSON:JavaScript Object Notation 【JavaScript 对象表示法】 JSON 是存储和交换文本信息的语法。类似...

2565
来自专栏weixuqin 的专栏

spring 学习(四): spring 的 jdbcTemplate 操作

spring 针对 javaee 的每一层,都提供了相应的解决技术,jdbcTemplate 的主要操作在 dao 层。

502

扫码关注云+社区