arangodb / arangodb-java-driver

The official ArangoDB Java driver.

Repository from Github https://github.comarangodb/arangodb-java-driverRepository from Github https://github.comarangodb/arangodb-java-driver

Version 7: How to ignore POJO fields for arangodb but serialize for outgoing as JSON with jackson

lorling88 opened this issue · comments

Hi there, im running on the latest version 7 and ran into this issue.
Before version 7, I had been using "com.arangodb.velocypack.annotations.Expose" to ignore fields being used by arangodb driver,
for example:
public class AAA {
private boolean memberKey;
Expose(serialize=false,deserialize=false) private boolean isStatusActive;
}
for this instance, when I insert, select, replace, etc, the field memberKey will be used and field "isStatusActive" will be ignored by arangodb and I can serialize both "memberKey" and "isStatusActive" for JSON text.

But now after version7, if I put in "@JsonIgnore private boolean isStatusActive" by Jackson "com.fasterxml.jackson.annotation.JsonIgnore", it will be ignore by both arangodb and jackson serialization.
I had just began to learn about jackson so maybe I had missed out some features which can bypass my issue here.

Please kindly advise.

Hi @lorling88,
to work around it you can either:

  1. use different classes in different layers of your application: you can use the entity class PersistentAAA in the persistence layer and WebAAA in the web layer. This would allow for customizing serialization and deserialization in different layers without interfereing with each other. Nonetheless this comes with an additional cost: you need to maintain 2 classes and convert between them.

  2. you can customize the ArangoDB driver JacksonSerde with custom annotations, e.g. in the following snippet you can see how to create a @ArangoIgnore annotation that is equivalent to Jackson @JsonIgnore, but it will only be considered by the ArangoDB serde and not by other Jackson instances in your application:

@Target({ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface ArangoAnnotationsInside {
}

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@ArangoAnnotationsInside
@JsonIgnore
@interface ArangoIgnore {
}

class AAA {
    public boolean memberKey;
    @ArangoIgnore
    public boolean isStatusActive;
}

// ...
//

JacksonSerde serde = JacksonSerde.of(ContentType.JSON)
        .configure((mapper) -> mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
            @Override
            public boolean isAnnotationBundle(Annotation ann) {
                return ann.annotationType().getAnnotation(ArangoAnnotationsInside.class) != null;
            }
        }));

ArangoDB adb = new ArangoDB.Builder()
        .serde(serde)
        // ...
        .build();

In my opinion, (1) is a better choice for big projects, while (2) could be suitable for smaller ones.

Hi @rashtao,

Thanks for your helpful reply and I had learnt something new about jackson lib.
I went for your method (2) and its working!
Cheers!

You are welcome @lorling88 !

Please note that I made a small mistake in my snippet, the correct serde configuration should be:

JacksonSerde serde = JacksonSerde.of(ContentType.JSON)
                .configure((mapper) -> mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
                    @Override
                    public boolean isAnnotationBundle(Annotation ann) {
                        return ann.annotationType().getAnnotation(ArangoAnnotationsInside.class) != null || super.isAnnotationBundle(ann);
                    }
                }));

I added here the invocation to super.isAnnotationBundle(ann), to handle also @JacksonAnnotationsInside annotations, which is required to make properly work document annotations like @Key, @Rev and others in com.arangodb.serde.jackson package.

Hi @rashtao,

I had added the additional.
Thanks alot!