DEV Community

André Laugks
André Laugks

Posted on • Edited on

Using nested annotations for key-value pairs in a custom annotation

Introduction

In my article "Using a hashmap in a custom annotation" I explained how to use a HashMap in an annotation using an Enum Constant.

Annotations are allowed as type in an annotation. This means that nested annotations can be used to define key-value pairs in a custom annotation.

List of supported Types in Annotations

Annotations

Two customs annotations are required. The first annotation (e.g. MapItem) containing a key-value pair and the second annotation (e.g. MapItems) containing a list of MapItem annotations.

Custom Annotation @MapItem

The annotation @MapItem represents a single key-value pair.

@Target(ElementType.FIELD) public @interface MapItem { String key(); String value(); } 
Enter fullscreen mode Exit fullscreen mode

Custom Annotation @MapItems

The annotation @MapItems defines a list of MapItem.

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface MapItems { MapItem[] items(); } 
Enter fullscreen mode Exit fullscreen mode

Functional Test

The list of @MapItem annotations are set in the @MapItems annotation.

class ExampleDto { @MapItems(items = { @MapItem(key = "1", value = "MALE"), @MapItem(key = "2", value = "FEMALE"), @MapItem(key = "6", value = "DIVERS") }) public String salutation; } 
Enter fullscreen mode Exit fullscreen mode

The MapItemsTest tests the MapItems annotation. The test is done on the salutation field.

To demonstrate how the list of @MapItem can be used, I create a HashMap from @MapItem and compare it to an expected HashMap.

class MapItemsTest { @Test void testMapItems() throws NoSuchFieldException { Field field = ExampleDto.class.getDeclaredField("salutation"); field.setAccessible(true); MapItems annotation = field.getAnnotation(MapItems.class); Map<String, String> mappingItems = Arrays .stream(annotation.items()) .collect( Collectors.toMap( MapItem::key, MapItem::value ) ); assertEquals( new HashMap<>() {{ put("1", "MALE"); put("2", "FEMALE"); put("6", "DIVERS"); }}, mappingItems ); } } 
Enter fullscreen mode Exit fullscreen mode

Conclusion

Pro

It is a smart solution and easy to implement.

Contra

If the key-value pairs are to be used in a validator, for example, they must be fetched indirectly.

Full example

https://github.com/alaugks/article-annotation-key-value-pairs

Related article

Top comments (0)