Vyřešil jsem to pomocí CustomizedTypeAdapterFactory. Viz tato otázka
V zásadě nejprve napište přizpůsobený adaptér:
public abstract class CustomizedTypeAdapterFactory<C>
implements TypeAdapterFactory
{
private final Class<C> customizedClass;
public CustomizedTypeAdapterFactory(Class<C> customizedClass) {
this.customizedClass = customizedClass;
}
@SuppressWarnings("unchecked") // we use a runtime check to guarantee that 'C' and 'T' are equal
public final <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
return type.getRawType() == customizedClass
? (TypeAdapter<T>) customizeMyClassAdapter(gson, (TypeToken<C>) type)
: null;
}
private TypeAdapter<C> customizeMyClassAdapter(Gson gson, TypeToken<C> type) {
final TypeAdapter<C> delegate = gson.getDelegateAdapter(this, type);
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
return new TypeAdapter<C>() {
@Override public void write(JsonWriter out, C value) throws IOException
{
JsonElement tree = delegate.toJsonTree(value);
beforeWrite(value, tree);
elementAdapter.write(out, tree);
}
@Override public C read(JsonReader in) throws IOException {
JsonElement tree = elementAdapter.read(in);
afterRead(tree);
return delegate.fromJsonTree(tree);
}
};
}
/**
* Override this to muck with {@code toSerialize} before it is written to
* the outgoing JSON stream.
*/
protected void beforeWrite(C source, JsonElement toSerialize) {
}
/**
* Override this to muck with {@code deserialized} before it parsed into
* the application type.
*/
protected void afterRead(JsonElement deserialized) {
}
}
A pak vytvořte podtřídu pro všechny třídy, které je třeba vzít v úvahu. Musíte vytvořit jeden pro každou třídu obsahující long (v tomto případě). Ale nemusíte serializovat nic kromě dlouhé hodnoty (a jakýchkoli dalších specifických hodnot bson)
public class MyTestObjectTypeAdapterFactory extends CustomizedTypeAdapterFactory<MyTestObject>
{
public MyTestObjectTypeAdapterFactory()
{
super(MyTestObject.class);
}
@Override
protected void beforeWrite(MyTestObject source, JsonElement toSerialize)
{
//you could convert back the other way here, I let mongo's document parser take care of that.
}
@Override
protected void afterRead(JsonElement deserialized)
{
JsonObject timestamp = deserialized.getAsJsonObject().get("timestamp").getAsJsonObject();
deserialized.getAsJsonObject().remove("timestamp");
deserialized.getAsJsonObject().add("timestamp",timestamp.get("$numberLong"));
}
}
a poté vygenerujte Gson pomocí:
Gson gson = new GsonBuilder().registerTypeAdapterFactory(new MyTestObjectTypeAdapterFactory()).create();