package com.hubspot.jackson.datatype.protobuf; import static com.hubspot.jackson.datatype.protobuf.util.ObjectMapperHelper.camelCase; import static org.assertj.core.api.Assertions.assertThat; import java.util.EnumSet; import java.util.HashSet; import java.util.Set; import org.junit.BeforeClass; import org.junit.Test; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.CaseFormat; import com.google.common.base.Enums; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.ExtensionRegistry; import com.google.protobuf.ExtensionRegistry.ExtensionInfo; import com.hubspot.jackson.datatype.protobuf.util.TestExtensionRegistry; import com.hubspot.jackson.datatype.protobuf.util.TestProtobuf.AllFields; public class JsonInclusionTest { private static final EnumSet<Include> EXCLUDED_VALUES = presentValues("ALWAYS", "USE_DEFAULTS", "CUSTOM"); private static final ExtensionRegistry EXTENSION_REGISTRY = TestExtensionRegistry.getInstance(); private static Set<String> allFields; private static Set<String> allExtensionFields; private static Set<String> arrayFields; private static Set<String> arrayExtensionFields; @BeforeClass public static void setup() { allFields = new HashSet<>(); arrayFields = new HashSet<>(); Descriptor descriptor = AllFields.getDescriptor(); for (FieldDescriptor field : descriptor.getFields()) { allFields.add(translate(field.getName())); if (field.isRepeated()) { arrayFields.add(translate(field.getName())); } } allExtensionFields = new HashSet<>(); arrayExtensionFields = new HashSet<>(); ExtensionRegistryWrapper extensionRegistry = ExtensionRegistryWrapper.wrap(EXTENSION_REGISTRY); for (ExtensionInfo extensionInfo : extensionRegistry.getExtensionsByDescriptor(descriptor)) { allExtensionFields.add(translate(extensionInfo.descriptor.getName())); if (extensionInfo.descriptor.isRepeated()) { arrayExtensionFields.add(translate(extensionInfo.descriptor.getName())); } } } @Test public void itWritesMissingFieldsAsNullWhenSerializationIncludeIsAlways() { AllFields message = AllFields.getDefaultInstance(); JsonNode node = mapper(Include.ALWAYS).valueToTree(message); for (String field : allFields) { assertThat(node.has(field)).isTrue(); if (arrayFields.contains(field)) { assertThat(node.get(field).isArray()); } else { assertThat(node.get(field).isNull()); } } for (String field : allExtensionFields) { assertThat(node.has(field)).isFalse(); } } @Test public void itOnlyWritesArrayFieldsWhenSerializationIncludeIsNotAlways() { AllFields message = AllFields.getDefaultInstance(); for (Include inclusion : EnumSet.complementOf(EXCLUDED_VALUES)) { JsonNode node = mapper(inclusion).valueToTree(message); for (String field : allFields) { if (arrayFields.contains(field)) { assertThat(node.has(field)).isTrue(); assertThat(node.get(field).isArray()); } else { assertThat(node.has(field)).isFalse(); } } for (String field : allExtensionFields) { assertThat(node.has(field)).isFalse(); } } } @Test public void itWritesMissingExtensionFieldsAsNullWhenSerializationIncludeIsAlways() { AllFields message = AllFields.getDefaultInstance(); JsonNode node = mapper(Include.ALWAYS, EXTENSION_REGISTRY).valueToTree(message); for (String field : allExtensionFields) { assertThat(node.has(field)).isTrue(); if (arrayExtensionFields.contains(field)) { assertThat(node.get(field).isArray()); } else { assertThat(node.get(field).isNull()); } } } @Test public void itOnlyWritesArrayExtensionFieldsWhenSerializationIncludeIsNotAlways() { AllFields message = AllFields.getDefaultInstance(); for (Include inclusion : EnumSet.complementOf(EXCLUDED_VALUES)) { JsonNode node = mapper(inclusion, EXTENSION_REGISTRY).valueToTree(message); for (String field : allExtensionFields) { if (arrayExtensionFields.contains(field)) { assertThat(node.has(field)).isTrue(); assertThat(node.get(field).isArray()); } else { assertThat(node.has(field)).isFalse(); } } } } private static String translate(String fieldName) { return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, fieldName); } private static ObjectMapper mapper(Include inclusion) { return camelCase().copy().setSerializationInclusion(inclusion); } private static ObjectMapper mapper(Include inclusion, ExtensionRegistry extensionRegistry) { return camelCase(extensionRegistry).copy().setSerializationInclusion(inclusion); } private static EnumSet<Include> presentValues(String... values) { EnumSet<Include> set = EnumSet.noneOf(Include.class); for (String value : values) { set.addAll(Enums.getIfPresent(Include.class, value).asSet()); } return set; } }