java:java.util.BitSet对象的Jackson序列化和反序列化实现

23 篇文章 1 订阅

java.util.BitSet是个非常方便的比特位数据存储和操作类,一个 bit 具有2个值:0和1,正好可以用来表示 false 和 true,适用于判断“数据是否存在”的场景。
但是,这个从JDK1.0版本就存在的类,Jackson,Fastjson这些主流的JSON工具却并没有对它提供序列化和反序列化支持。
所以如果要在自己的数据结构中用到BitSet,就要自己实现序列化和反序列化。
上篇博客《java:java.util.BitSet对象的Fastjson序列化和反序列化实现》介绍了Fastjson实现,本文说明Jackson如何支持BitSet类型的序列化和反序列化
以下是BitSet对象的Jackson序列化和反序列化实现,
主要思路就是在序列化过程中将BitSet的数据转为JSON数组(如[7707,8822]或单个数字(当设置SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED特性时).
在反序列化阶段,根据TOKEN类型不同,将数据序列化为long[]再调用BitSet.valueOf方法转为BitSet对象返回。

/**
 * {@link BitSet} 的JACKSON序列化和反序列化实现
 * @author guyadong
 * @since 3.30.1
 */
public class BitSetJacksonCodec{
	public static final Deserializer DESERIALIZER = new Deserializer();
	public static final Serializer SERIALIZER = new Serializer();
	/**
	 * {@link BitSet}反序列化实现
	 */
	public static class Deserializer extends JsonDeserializer<BitSet> {
		private final JsonDeserializer<?> longArrayDeserializer = PrimitiveArrayDeserializers.forType(long.class);
		@Override
		public BitSet deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
	        ObjectMapper mapper = (ObjectMapper) jp.getCodec();
	        switch(jp.currentTokenId()) {
	        case JsonTokenId.ID_NULL:
	        	jp.nextToken();
	        	return null;
	        case JsonTokenId.ID_START_ARRAY:{
	        	long[] longs = (long[]) longArrayDeserializer.deserialize(jp, ctxt);
	        	return BitSet.valueOf(longs);
	        }
	        case JsonTokenId.ID_STRING:{
	        	/** 将文本递归解析 */
	        	String text = jp.getText();
	        	jp.nextToken();
	        	return mapper.readValue(text, BitSet.class);
	        }
	        default:{
	        	/** 数字类型:VALUE_NUMBER_INT */
	        	BitSet bitSet = BitSet.valueOf(new long[] {jp.getNumberValue().longValue()});
	        	jp.nextToken();
	        	return bitSet;
	        }
	        }
		}

	}
	/**
	 * {@link BitSet}序列化实现
	 */
	public static class Serializer extends JsonSerializer<BitSet> {
		@SuppressWarnings({ "rawtypes" })
		private final JsonSerializer longArraySerializer = StdArraySerializers.findStandardImpl(long[].class);
		@SuppressWarnings("unchecked")
		@Override
		public void serialize(BitSet value, JsonGenerator gen, SerializerProvider serializers)
				throws IOException, JsonProcessingException {
			if(null == value) {
				gen.writeNull();
			}else {
				longArraySerializer.serialize(value.toLongArray(), gen, serializers);
			}
		}

	}
}

测试及调用示例:

	@Test
	public void test5JacksonCodec() {
		try {
			BitSet bitSet = BitSet.valueOf(new byte[] {27,30});
			ObjectMapper mapper = new ObjectMapper();
			SimpleModule module = new SimpleModule()
					.addDeserializer(BitSet.class, BitsetJacksonCodec.DESERIALIZER)
					.addSerializer(BitSet.class, BitsetJacksonCodec.SERIALIZER);
			mapper.registerModule(module);
			{
				/** 序列化为数组 */ 
				String json = mapper.writeValueAsString(bitSet);
				log("JSON:{}",json);
				assertTrue(json.equals("[7707]"));
				BitSet parsed = mapper.readValue(json, BitSet.class);
				assertTrue(bitSet.equals(parsed));
			}
			{
				mapper.enable(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED);
				/** 序列化为数字 */ 
				String json = mapper.writeValueAsString(bitSet);
				log("JSON:{}",json);
				assertTrue(json.equals("7707"));
				BitSet parsed = mapper.readValue(json, BitSet.class);
				assertTrue(bitSet.equals(parsed));
			}
			{
				mapper.disable(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED);
				/** 序列化为数字 */ 
				String json = mapper.writeValueAsString(new TestBean(bitSet, 32));
				log("JSON:{}",json);
				assertTrue(json.equals("{\"bitSet\":[7707],\"age\":32}"));
				TestBean parsed = mapper.readValue(json, TestBean.class);
				assertTrue(bitSet.equals(parsed.bitSet));
			}
		}catch (Throwable e) {
			e.printStackTrace();
			fail();
		}
	}
	public static class TestBean{
		BitSet bitSet;
		Integer age;

		public TestBean() {
		}

		public TestBean(BitSet bitSet, Integer age) {
			this.bitSet = bitSet;
			this.age = age;
		}

		public BitSet getBitSet() {
			return bitSet;
		}

		public void setBitSet(BitSet bitSet) {
			this.bitSet = bitSet;
		}

		public Integer getAge() {
			return age;
		}

		public void setAge(Integer age) {
			this.age = age;
		}
	}

完整实现代码参见码云仓库:https://gitee.com/l0km/sql2java/blob/dev/sql2java-base/src/main/java/gu/sql2java/json/BitSetJacksonCodec.java
完整测试代码参见码云仓库:https://gitee.com/l0km/sql2java/blob/dev/sql2java-base/src/test/java/gu/sql2java/BitSetJsonCodecTest.java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值