Reputation: 219
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
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
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
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
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
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
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