I would like to serialize/deserialize java.util.Bitset in JSON format. This code:
BitSet bs = new BitSet(10);
bs.set(1);
bs.set(5);
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(System.out, bs);
prints {"empty":false} as output. Should I write my own serializer/deserializer or is there some better way?
try adding:
mapper.registerModule(new Jdk8Module());
Jacksons's own unit tests have ones for BitSet. You shouldn't need to roll your own.
ObjectMapper.writeValue() will look into the object class and find all getSomething methods and isSomething methods to generate json based on the methods name.
Your result {"empty":false} is come from this method of BitSet class:
public boolean isEmpty() {...}
So I think you shoud write your own serializer/deserializer instead of using ObjectMapper serialization mechanism
Thank you! I think, I have a solution which seems to be more space and memory saving to me - it's important due to proccessing huge amount of data. The folowing solution did it:
public class BitSetSerializer extends JsonSerializer<BitSet>
{
@Override
public void serialize(BitSet value, JsonGenerator gen, SerializerProvider serializers)
throws IOException, JsonProcessingException
{
gen.writeStartArray();
for (long l : value.toLongArray())
{
gen.writeNumber(l);
}
gen.writeEndArray();
}
@Override
public Class<BitSet> handledType()
{
return BitSet.class;
}
}
public class BitSetDeserializer extends JsonDeserializer<BitSet>
{
@Override
public BitSet deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException, JsonProcessingException
{
ArrayList<Long> l = new ArrayList<Long>();
JsonToken token;
while (!JsonToken.END_ARRAY.equals(token = jsonParser.nextValue()))
{
if (token.isNumeric())
{
l.add(jsonParser.getLongValue());
}
}
return BitSet.valueOf(Longs.toArray(l));
}
}
SimpleModule testModule = new SimpleModule("MyModule");
testModule.addSerializer(new BitSetSerializer());
testModule.addDeserializer(BitSet.class, new BitSetDeserializer());
BitSet bs = new BitSet();
bs.set(1);
bs.set(1500);
System.out.println(bs);
ObjectMapper mapper = new ObjectMapper();
// mapper.registerModule(new Jdk8Module()); //serialization result takes too much space
mapper.registerModule(testModule);
String val = mapper.writeValueAsString(bs);
System.out.println(val);
BitSet bs2 = mapper.readValue(val, BitSet.class);
System.out.println(bs2);
Try with custom serializer and deserializer for Bitset.
Serializer:
public class BitSetSerializer extends JsonSerializer<BitSet> {
@Override
public void serialize(BitSet value, JsonGenerator gen,
SerializerProvider serializers) throws IOException, JsonProcessingException {
gen.writeStartArray();
for (int i = 0; i < value.length(); i++) {
gen.writeBoolean(value.get(i));
}
gen.writeEndArray();
}
}
Deserilizer:
public class BitSetDeserializer extends JsonDeserializer<BitSet> {
@Override
public BitSet deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException, JsonProcessingException {
BitSet ret = new BitSet();
int i = 0;
JsonToken token;
while (!JsonToken.END_ARRAY.equals(token = jsonParser.nextValue())) {
if (JsonToken.VALUE_TRUE.equals(token))
ret.set(i);
i++;
}
return ret;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With