Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON Serialization of BitSet doesn't work

Tags:

java

json

jackson

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?

like image 585
Dimitri Tenenbaum Avatar asked Aug 03 '18 12:08

Dimitri Tenenbaum


4 Answers

try adding:

 mapper.registerModule(new Jdk8Module());

Jacksons's own unit tests have ones for BitSet. You shouldn't need to roll your own.

like image 157
Dan Avatar answered Nov 15 '22 16:11

Dan


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

like image 31
Sann Tran Avatar answered Nov 15 '22 16:11

Sann Tran


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);
like image 1
Dimitri Tenenbaum Avatar answered Nov 15 '22 17:11

Dimitri Tenenbaum


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;
}
}
like image 1
GolamMazid Sajib Avatar answered Nov 15 '22 16:11

GolamMazid Sajib