diff --git a/pom.xml b/pom.xml
index dffcb646c..970c69c94 100644
--- a/pom.xml
+++ b/pom.xml
@@ -86,6 +86,11 @@
jackson-dataformat-yaml
2.14.0
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jdk8
+ 2.14.0
+
@@ -150,6 +155,10 @@
com.fasterxml.jackson.dataformat
jackson-dataformat-yaml
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jdk8
+
ch.obermuhlner
big-math
diff --git a/src/main/java/com/hubspot/jinjava/JinjavaConfig.java b/src/main/java/com/hubspot/jinjava/JinjavaConfig.java
index 9cdee6f85..3cff4787c 100644
--- a/src/main/java/com/hubspot/jinjava/JinjavaConfig.java
+++ b/src/main/java/com/hubspot/jinjava/JinjavaConfig.java
@@ -19,6 +19,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.google.common.collect.ImmutableSet;
import com.hubspot.jinjava.el.JinjavaInterpreterResolver;
import com.hubspot.jinjava.el.JinjavaObjectUnwrapper;
@@ -158,7 +159,7 @@ private JinjavaConfig(Builder builder) {
private ObjectMapper setupObjectMapper(@Nullable ObjectMapper objectMapper) {
if (objectMapper == null) {
- objectMapper = new ObjectMapper();
+ objectMapper = new ObjectMapper().registerModule(new Jdk8Module());
if (legacyOverrides.isUseSnakeCasePropertyNaming()) {
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
}
diff --git a/src/main/java/com/hubspot/jinjava/objects/serialization/PyishSerializable.java b/src/main/java/com/hubspot/jinjava/objects/serialization/PyishSerializable.java
index b967cb828..da9dd29c5 100644
--- a/src/main/java/com/hubspot/jinjava/objects/serialization/PyishSerializable.java
+++ b/src/main/java/com/hubspot/jinjava/objects/serialization/PyishSerializable.java
@@ -6,6 +6,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.google.common.annotations.Beta;
import com.hubspot.jinjava.interpret.DeferredValueException;
import com.hubspot.jinjava.objects.PyWrapper;
@@ -19,6 +20,7 @@ public interface PyishSerializable extends PyWrapper {
ObjectWriter SELF_WRITER = new ObjectMapper(
new JsonFactoryBuilder().quoteChar('\'').build()
)
+ .registerModule(new Jdk8Module())
.writer(PyishPrettyPrinter.INSTANCE)
.with(PyishCharacterEscapes.INSTANCE);
diff --git a/src/test/java/com/hubspot/jinjava/util/EagerExpressionResolverTest.java b/src/test/java/com/hubspot/jinjava/util/EagerExpressionResolverTest.java
index e634ae0fc..1ee802810 100644
--- a/src/test/java/com/hubspot/jinjava/util/EagerExpressionResolverTest.java
+++ b/src/test/java/com/hubspot/jinjava/util/EagerExpressionResolverTest.java
@@ -35,6 +35,7 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.After;
@@ -93,6 +94,15 @@ private JinjavaInterpreter getInterpreter(boolean evaluateMapKeys) throws Except
this.getClass().getDeclaredMethod("sleeper")
)
);
+ jinjava
+ .getGlobalContext()
+ .registerFunction(
+ new ELFunctionDefinition(
+ "",
+ "optionally",
+ this.getClass().getDeclaredMethod("optionally", boolean.class)
+ )
+ );
interpreter = new JinjavaInterpreter(jinjava.newInterpreter());
context = interpreter.getContext();
context.put("deferred", DeferredValue.instance());
@@ -124,6 +134,14 @@ public void itResolvesDeferredBoolean() {
assertThat(interpreter.resolveELExpression(partiallyResolved, 1)).isEqualTo(true);
}
+ @Test
+ public void itSerializesNestedOptional() {
+ assertThat(eagerResolveExpression("[optionally(true)]").toString())
+ .isEqualTo("['1'|allow_snake_case]");
+ assertThat(eagerResolveExpression("[optionally(false)]").toString())
+ .isEqualTo("[null|allow_snake_case]");
+ }
+
@Test
public void itResolvesDeferredList() {
context.put("foo", "foo_val");
@@ -877,6 +895,10 @@ public static long sleeper() throws InterruptedException {
return sleepTime;
}
+ public static Optional optionally(boolean hasValue) {
+ return Optional.of(hasValue).filter(Boolean::booleanValue).map(ignored -> "1");
+ }
+
private static class Foo {
private final String bar;