2

I'm using Google GSON in my Java application.

Imagine the following situation: A new JSON attribute was added in version 1.2.1. How can I use this in the @Since annotation? Obviously, @Since(1.2.1) is not possible because 1.2.1 is not a valid double. My version format is <major>.<minor>.<patch>.

Another thing I noticed if I have version 1.20, GSON sees it as a lower version than e.g version 1.3.

Any ideas how to solve this? Could maybe something like a custom excluder work? (does that even exist?)

Apart from the version issue, I noticed the @Since annotation can be used for classes, too. I couldn't find any documentation about this. I would appreciate it if someone could give an explanation why this is useful.

Thomas Vos
  • 12,271
  • 5
  • 33
  • 71

1 Answers1

2

It looks like the @Since annotation is a little limited and will not work for you. You are correct in needing a custom exclusion strategy. Something like below will work:

  1. Create your own annotation for versions to use instead of @Since:

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD, ElementType.TYPE})
    @interface VersionAnnotation {
        String versionNumber();
    }
    
  2. Custom exclusion strategy:

    class VersionExclusionStrategy implements ExclusionStrategy {
    
        private String versionNumber;
    
        VersionExclusionStrategy(String versionNumber) {
            this.versionNumber = versionNumber;
        }
    
        @Override
        public boolean shouldSkipClass(Class<?> classType) {
            VersionAnnotation va = classType.getAnnotation(VersionAnnotation.class);
    
            return va != null && versionCompare(this.versionNumber, va.versionNumber()) < 0;
        }
    
        @Override
        public boolean shouldSkipField(FieldAttributes fieldAttributes) {
            VersionAnnotation va = fieldAttributes.getAnnotation(VersionAnnotation.class);
    
            return va != null && versionCompare(this.versionNumber, va.versionNumber()) < 0;
        }
    
        private static int versionCompare(String str1, String str2) {
            // TODO implement
        }
    }
    
  3. The versionCompare method is what will compare your version strings. I used one from an answer to this question: How do you compare two version Strings in Java?

  4. Usage:

    Gson gson = new GsonBuilder().setExclusionStrategies(new VersionExclusionStrategy("1.3")).create();
    

I'm not sure how this would be useful for classes. You can annotate the class so that you don't have to annotate all the class references in other classes, but that's about it.

tima
  • 1,498
  • 4
  • 20
  • 28
  • 1
    Thanks, I got it working. I already realised the default `@Since` annotation would't have worked, it's too limited. The annotation for a class is actually comes in quite handy. If a new "feature" is introduced in a newer API version, I can just annotate the class instead of every new field. It's much more readable that way. – Thomas Vos Jul 21 '17 at 09:32