I'm looking for a way to read a MongoDB document into a POJO using GSON. It works just fine until you run into stuff like date's and longs.
I would like to write a custom adapter for Gson which will convert any BSON encoded long. Reading this post I have created my own adapter:
public class BsonLongTypeAdapter extends TypeAdapter<Long>
{
    @Override
    public void write(JsonWriter out, Long value) throws IOException
    {
        out.beginObject()
           .name("$numberLong")
           .value(value.toString())
           .endObject();
    }
    @Override
    public Long read(JsonReader in) throws IOException
    {
        in.beginObject();
        assert "$numberLong".equals(in.nextName());
        Long value = in.nextLong();
        in.endObject();
        return value;
    }
}
I have defined the following tests to check if this works:
@Test
public void canWriteCorrectJSON() {
    Gson gson = new GsonBuilder().registerTypeAdapter(Long.class, new BsonLongTypeAdapter()).create();
    MyTestObject obj = new MyTestObject(1458569479431L);
    String gsonString = gson.toJson(obj);
    assertEquals("{\"timestamp\":{\"$numberLong\":\"1458569479431\"}}",gsonString);
}
@Test
public void canReadFromJSON() {
    Gson gson = new GsonBuilder().registerTypeAdapter(Long.class, new BsonLongTypeAdapter()).create();
    MyTestObject actualTaskObject = gson.fromJson("{\"timestamp\":{\"$numberLong\":\"1458569479431\"}}", MyTestObject.class);
    MyTestObject taskObject = new MyTestObject(1458569479431L);
    assertEquals(taskObject.getTimestamp(),actualTaskObject.getTimestamp());
}
private static class MyTestObject
{
    long timestamp;
    public MyTestObject(long ts)
    {
        timestamp = ts;
    }
    public long getTimestamp()
    {
        return timestamp;
    }
    public void setTimestamp(long timestamp)
    {
        this.timestamp = timestamp;
    }
}
The first (write) test works just fine, but the read test fails on:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a long but was BEGIN_OBJECT at line 1 column 15 path $.timestamp
Because the read function from my adapter is never called. I presume this might be because I want to map to MyTestObject and not to Long, but I don't want to have to write adapters for all classes that contain longs.
Is it possible to write an adapter for GSON that converts all BSON longs I send into it?