Jag löste det med en CustomizedTypeAdapterFactory. Se den här frågan
Skriv i princip först en anpassad adapter:
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) {
}
}
Och skapa sedan en underklass för alla klasser som måste beaktas. Du måste skapa en för varje klass som innehåller en lång (i det här fallet). Men du behöver inte serialisera något annat än det långa värdet (och alla andra bson-specifika värden)
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"));
}
}
och generera sedan Gson med:
Gson gson = new GsonBuilder().registerTypeAdapterFactory(new MyTestObjectTypeAdapterFactory()).create();