Dimitri Tenenbaum
Dimitri Tenenbaum

Reputation: 219

JSON Serialization of BitSet doesn't work

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?

Upvotes: 6

Views: 2060

Answers (6)

user24524471
user24524471

Reputation: 1

// Convert JSON string to BitSet
public static BitSet jsonToBitSet(String jsonString) {
    BitSet bitSet = new BitSet();
    try {
        JSONObject jsonObject = new JSONObject(jsonString);
        Iterator<String> keys = jsonObject.keys();
        while (keys.hasNext()) {
            String key = keys.next();
            int index = Integer.parseInt(key);
            boolean value = jsonObject.getBoolean(key);
            bitSet.set(index, value);
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return bitSet;
}

// Convert BitSet to JSON string
public static String bitSetToJSON(BitSet bitSet) {
    JSONObject jsonObject = new JSONObject();
    for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) {
        try {
            jsonObject.put(Integer.toString(i), bitSet.get(i));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    return jsonObject.toString();
}

public static void main(String[] args) {
    String jsonString = "{\"0\":true,\"2\":true,\"3\":true}";
    BitSet bitSet = jsonToBitSet(jsonString);
    System.out.println("BitSet: " + bitSet);

    String newJsonString = bitSetToJSON(bitSet);
    System.out.println("JSON String: " + newJsonString);
}

}

Upvotes: -1

Feraz Ahmad
Feraz Ahmad

Reputation: 1

import org.json.JSONException;
import org.json.JSONObject;
import java.util.BitSet;

public class JSONBitSetConverter {

    // Convert JSON string to BitSet
    public static BitSet jsonToBitSet(String jsonString) {
        BitSet bitSet = new BitSet();
        try {
            JSONObject jsonObject = new JSONObject(jsonString);
            String[] keys = JSONObject.getNames(jsonObject);
            if (keys != null) {
                for (String key : keys) {
                    int index = Integer.parseInt(key);
                    boolean value = jsonObject.getBoolean(key);
                    bitSet.set(index, value);
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return bitSet;
    }

    // Convert BitSet to JSON string
    public static String bitSetToJSON(BitSet bitSet) {
        JSONObject jsonObject = new JSONObject();
        for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) {
            try {
                jsonObject.put(Integer.toString(i), bitSet.get(i));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return jsonObject.toString();
    }

    public static void main(String[] args) {
        String jsonString = "{\"0\":true,\"2\":true,\"3\":true}";
        BitSet bitSet = jsonToBitSet(jsonString);
        System.out.println("BitSet: " + bitSet);

        String newJsonString = bitSetToJSON(bitSet);
        System.out.println("JSON String: " + newJsonString);
    }
}

Upvotes: -1

GolamMazid Sajib
GolamMazid Sajib

Reputation: 9447

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;
}
}

Upvotes: 1

Dimitri Tenenbaum
Dimitri Tenenbaum

Reputation: 219

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);

Upvotes: 1

Dan
Dan

Reputation: 1033

try adding:

 mapper.registerModule(new Jdk8Module());

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

Upvotes: 1

Sann Tran
Sann Tran

Reputation: 179

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

Upvotes: 1

Related Questions