22

All,

I'm trying to do the following:

public class SomClass
{
    public boolean x;
    public int y;
    public String z;
}       

SomClass s = new SomClass();
s.x = true;
s.y = 10;
s.z = "ZZZ";
Gson gson = new Gson();
String retVal = gson.toJson(s);
return retVal;

So this little snippet will produce:

{"x":true,"y":10,"z":"ZZZ"}

but what I need it to produce is:

{"x":0, "y":10,"z":"ZZZ"}

Can someone please give me some options? I'd prefer not to rewrite my booleans as ints as that will cause several issues with existing code (nonobvious, hard to read, hard to enforce, etc.)

Austin
  • 1,521
  • 5
  • 15
  • 27

2 Answers2

54

To make it "correct" way, you can use something like that

import java.lang.reflect.Type;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

public class BooleanSerializer implements JsonSerializer<Boolean>, JsonDeserializer<Boolean> {

    @Override
    public JsonElement serialize(Boolean arg0, Type arg1, JsonSerializationContext arg2) {
        return new JsonPrimitive(Boolean.TRUE.equals(arg0));
    }

    @Override
    public Boolean deserialize(JsonElement arg0, Type arg1, JsonDeserializationContext arg2) throws JsonParseException {
        return arg0.getAsInt() == 1;
    }
}

And then use it:

public class Main {

    public class Base {
        @Expose
        @SerializedName("class")
        protected String clazz = getClass().getSimpleName();
        protected String control = "ctrl";
    }

    public class Child extends Base {
        protected String text = "This is text";
        protected Boolean boolTest = false;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        Main m = new Main();
        GsonBuilder b = new GsonBuilder();
        BooleanSerializer serializer = new BooleanSerializer();
        b.registerTypeAdapter(Boolean.class, serializer);
        b.registerTypeAdapter(boolean.class, serializer);
        Gson gson = b.create();

        Child c = m.new Child();
        System.out.println(gson.toJson(c));
        String testStr = "{\"text\":\"This is text\",\"boolTest\":1,\"class\":\"Child\",\"control\":\"ctrl\"}";
        Child cc = gson.fromJson(testStr, Main.Child.class);
        System.out.println(gson.toJson(cc));
    }
}

Hope this helps someone :-)

Damian Walczak
  • 1,334
  • 14
  • 21
  • 1
    As IntelliJ pointed out for me, you can simplify your `deserialize` function into simply `return arg0.getAsInt() == 1` – Anthony Chuinard May 09 '14 at 22:28
  • It works for me with a slight modification: `b.registerTypeAdapter(boolean.class, new BooleanSerializer());` – Gavin Jun 30 '14 at 08:45
  • 1
    Thanks .its work for me...b.registerTypeAdapter(boolean.class, new BooleanSerializer()); same as @Gavin – dipali Mar 02 '15 at 05:30
  • According to docs http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/GsonBuilder.html#registerTypeAdapter(java.lang.reflect.Type,%20java.lang.Object) you should also register boolean.class b.registerTypeAdapter(Boolean.class, new BooleanSerializer()); b.registerTypeAdapter(boolean.class, new BooleanSerializer()); – Evandro P. Alves Apr 01 '15 at 11:29
  • @EvandroP.Alves thanks, I edited the answer to reflect your suggestion :) – Damian Walczak Apr 01 '15 at 14:37
  • This works on gson 2.3 onwards. https://github.com/google/gson/issues/378 – Dilini Rajapaksha Jul 14 '16 at 06:29
  • You just almost literally saved my life! Thanks a lot! – McSullivan Aug 05 '16 at 18:44
  • 1
    return new JsonPrimitive(arg0 ? 1 : 0); will crash if arg0 is null. Do Boolean.TRUE.equals(arg0) ... instead. – Ridcully Dec 20 '17 at 14:00
2

or this: Gson User Guide - Custom Serialization and Deserialization

Richard Le Mesurier
  • 29,432
  • 22
  • 140
  • 255
GreyBeardedGeek
  • 29,460
  • 2
  • 47
  • 67