Skip to content

Commit

Permalink
Parameter jackson2Configuration.view - select one @JsonView (vojt…
Browse files Browse the repository at this point in the history
  • Loading branch information
vojtechhabarta authored and mohasarc committed Jun 24, 2021
1 parent f02565f commit 7fa3e80
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,10 @@ public class Jackson2Configuration {
*/
public List<String> deserializerTypeMappings;

/**
* Specifies ObjectMapper's active view (as a fully-qualified class name).
* Properties can be annotated with <code>@JsonView</code> to indicate which views they are part of.
*/
public String view;

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class Jackson2ConfigurationResolved {
public Map<Class<? extends JsonSerializer>, String> serializerTypeMappings;
@SuppressWarnings("rawtypes")
public Map<Class<? extends JsonDeserializer>, String> deserializerTypeMappings;
public Class<?> view;

public static Jackson2ConfigurationResolved from(Jackson2Configuration configuration, ClassLoader classLoader) {
final Jackson2ConfigurationResolved resolved = new Jackson2ConfigurationResolved();
Expand All @@ -42,6 +43,7 @@ public static Jackson2ConfigurationResolved from(Jackson2Configuration configura
configuration.deserializerTypeMappings, "deserializerTypeMapping", classLoader, JsonDeserializer.class, Function.identity());
resolved.serializerTypeMappings = resolveClassMappings(
configuration.serializerTypeMappings, "serializerTypeMapping", classLoader, JsonSerializer.class, Function.identity());
resolved.view = configuration.view != null ? Settings.loadClass(classLoader, configuration.view, Object.class) : null;
return resolved;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.type.TypeReference;
Expand Down Expand Up @@ -253,7 +254,8 @@ protected DeclarationModel parseClass(SourceType<Class<?>> sourceClass) {
private BeanModel parseBean(SourceType<Class<?>> sourceClass, List<String> classComments) {
final List<PropertyModel> properties = new ArrayList<>();

final BeanHelpers beanHelpers = getBeanHelpers(sourceClass.type);
final Class<?> view = settings.jackson2Configuration != null ? settings.jackson2Configuration.view : null;
final BeanHelpers beanHelpers = getBeanHelpers(sourceClass.type, view);
if (beanHelpers != null) {
for (final Pair<BeanProperty, PropertyAccess> pair : beanHelpers.getPropertiesAndAccess()) {
final BeanProperty beanProperty = pair.getValue1();
Expand Down Expand Up @@ -386,7 +388,7 @@ private Type processIdentity(Type propertyType, BeanProperty beanProperty) {
if (identityInfo.generator() == ObjectIdGenerators.None.class) {
return null;
} else if (identityInfo.generator() == ObjectIdGenerators.PropertyGenerator.class) {
final BeanHelpers beanHelpers = getBeanHelpers(cls);
final BeanHelpers beanHelpers = getBeanHelpers(cls, null);
if (beanHelpers == null) {
return null;
}
Expand Down Expand Up @@ -511,7 +513,7 @@ private static <T extends Annotation> Pair<Class<?>, T> getAnnotationRecursive(C
return Pair.of(null, null);
}

private BeanHelpers getBeanHelpers(Class<?> beanClass) {
private BeanHelpers getBeanHelpers(Class<?> beanClass, Class<?> view) {
if (beanClass == null) {
return null;
}
Expand All @@ -522,7 +524,7 @@ private BeanHelpers getBeanHelpers(Class<?> beanClass) {
final BeanSerializerHelper beanSerializerHelper = createBeanSerializerHelper(javaType);
final BeanDeserializerHelper beanDeserializerHelper = createBeanDeserializerHelper(javaType);
if (beanSerializerHelper != null || beanDeserializerHelper != null) {
return new BeanHelpers(beanClass, beanSerializerHelper, beanDeserializerHelper);
return new BeanHelpers(beanClass, view, beanSerializerHelper, beanDeserializerHelper);
}
return null;
}
Expand Down Expand Up @@ -560,16 +562,18 @@ private BeanDeserializerHelper createBeanDeserializerHelper(JavaType javaType) {

// for tests
protected List<BeanProperty> getBeanProperties(Class<?> beanClass) {
return getBeanHelpers(beanClass).getProperties();
return getBeanHelpers(beanClass, null).getProperties();
}

private static class BeanHelpers {
public final Class<?> beanClass;
public final Class<?> view;
public final BeanSerializerHelper serializer;
public final BeanDeserializerHelper deserializer;

public BeanHelpers(Class<?> beanClass, BeanSerializerHelper serializer, BeanDeserializerHelper deserializer) {
public BeanHelpers(Class<?> beanClass, Class<?> view, BeanSerializerHelper serializer, BeanDeserializerHelper deserializer) {
this.beanClass = beanClass;
this.view = view;
this.serializer = serializer;
this.deserializer = deserializer;
}
Expand All @@ -595,8 +599,10 @@ private List<Pair<BeanProperty, BeanProperty>> getPropertiesPairs() {
final List<Pair<BeanProperty, BeanProperty>> properties = Stream
.concat(
serializableProperties.stream()
.filter(this::inView)
.map(property -> Pair.of(property, getBeanProperty(deserializableProperties, property.getName()))),
deserializableProperties.stream()
.filter(this::inView)
.filter(property -> getBeanProperty(serializableProperties, property.getName()) == null)
.map(property -> Pair.of((BeanProperty) null, property))
)
Expand All @@ -622,6 +628,18 @@ private List<Pair<BeanProperty, BeanProperty>> getPropertiesPairs() {
return properties;
}

private boolean inView(BeanProperty beanProperty) {
if (view == null) {
return true;
}
final JsonView annotation = beanProperty.getAnnotation(JsonView.class);
if (annotation == null || annotation.value().length == 0) {
return true;
}
return Stream.of(annotation.value())
.anyMatch(v -> v.isAssignableFrom(view));
}

private static BeanProperty getBeanProperty(List<BeanProperty> properties, String name) {
return properties.stream()
.filter(dp -> Objects.equals(dp.getName(), name))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@

package cz.habarta.typescript.generator;

import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Assert;
import org.junit.Test;


public class JsonViewTest {

public static void main(String[] args) throws Exception {
final SomeClass parent1 = new SomeClass();
parent1.id = 22;
final SomeClass some1 = new SomeClass();
some1.id = 13;
some1.parentID = 22;
some1.parent = parent1;
some1.someProperty = "f";
some1.anotherProperty = 10L;

final ObjectMapper objectMapper1 = new ObjectMapper();
objectMapper1.setConfig(objectMapper1.getSerializationConfig().withView(Views.REST.class));
final String json1 = objectMapper1.writeValueAsString(some1);
System.out.println(json1);

final ObjectMapper objectMapper2 = new ObjectMapper();
objectMapper2.setConfig(objectMapper2.getDeserializationConfig().withView(Views.REST.class));
final String json2 = "{\"id\":13,\"parentID\":22,\"parent\":{\"id\":22,\"parentID\":null,\"parent\":null,\"someProperty\":null,\"anotherProperty\":null},\"someProperty\":\"f\",\"anotherProperty\":10}";
final SomeClass some2 = objectMapper2.readValue(json2, SomeClass.class);
System.out.println(some2.anotherProperty);
}

@Test
public void test1() {
final Settings settings = TestUtils.settings();
settings.jackson2Configuration = new Jackson2ConfigurationResolved();
settings.jackson2Configuration.view = Views.REST.class;
final String output = new TypeScriptGenerator(settings).generateTypeScript(Input.from(SomeClass.class));
assertOutput(output);
}

@Test
public void test2() {
final Settings settings = TestUtils.settings();
settings.jackson2Configuration = new Jackson2ConfigurationResolved();
settings.jackson2Configuration.view = Views.REST.class;
final String output = new TypeScriptGenerator(settings).generateTypeScript(Input.from(SomeClassGetters.class));
assertOutput(output);
}

private static void assertOutput(String output) {
Assert.assertTrue(output.contains("id:"));
Assert.assertTrue(output.contains("parentID:"));
Assert.assertTrue(!output.contains("parent:"));
Assert.assertTrue(output.contains("someProperty:"));
Assert.assertTrue(!output.contains("anotherProperty:"));
}

public static class Views {

public static class BaseConfig {
}

public static class REST {
}

public static class Exclude {
}

}

public static class SomeClass {

@JsonView({Views.BaseConfig.class, Views.REST.class})
public Integer id;

@JsonView({Views.BaseConfig.class, Views.REST.class})
public Integer parentID;

@JsonView(Views.Exclude.class)
public SomeClass parent;

@JsonView(Views.REST.class)
public String someProperty;

@JsonView(Views.BaseConfig.class)
public Long anotherProperty;

}

public static class SomeClassGetters {

private Integer id;
private Integer parentID;
private SomeClass parent;
private String someProperty;
private Long anotherProperty;

@JsonView({Views.BaseConfig.class, Views.REST.class})
public Integer getId() {
return id;
}

@JsonView({Views.BaseConfig.class, Views.REST.class})
public Integer getParentID() {
return parentID;
}

@JsonView(Views.Exclude.class)
public SomeClass getParent() {
return parent;
}

@JsonView(Views.REST.class)
public String getSomeProperty() {
return someProperty;
}

@JsonView(Views.BaseConfig.class)
public Long getAnotherProperty() {
return anotherProperty;
}

}

}

0 comments on commit 7fa3e80

Please sign in to comment.