sql >> Database teknologi >  >> NoSQL >> MongoDB

Læs BSON (mongoDB) ind i POJO ved hjælp af GSON og TypeAdapter

Jeg løste det ved hjælp af en CustomizedTypeAdapterFactory. Se dette spørgsmål

Grundlæggende skal du først skrive en tilpasset 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) {
    }
}

Og lav så en underklasse for alle klasser, der skal tages hensyn til. Du skal oprette en for hver klasse, der indeholder en lang (i dette tilfælde). Men du behøver ikke at serialisere andet end den lange værdi (og eventuelle andre bson-specifikke værdier)

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"));
    }
}

og generer derefter Gson med:

Gson gson = new GsonBuilder().registerTypeAdapterFactory(new MyTestObjectTypeAdapterFactory()).create();



  1. Opdatering i forEach på mongodb shell

  2. Hvilken Mongo-instans i Replica Set kaldte applikationen?

  3. Sidekiq finder ikke registreringer for Rails Active Job

  4. Hvordan bruger man interface type som en model i mgo (Go)?