Skip to content

Commit 12f3d60

Browse files
committed
Make null values loop-able.
1 parent 0c47c7f commit 12f3d60

3 files changed

Lines changed: 37 additions & 1 deletion

File tree

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.hubspot.jinjava.interpret;
2+
3+
/**
4+
* Marker object of a `null` value. A null value in the map is usually considered
5+
* the key does not exist. For example map = {"a": null}, if map.get("a") == null,
6+
* we treat it as the there is not key "a" in the map.
7+
*/
8+
public final class NullValue {
9+
public static final NullValue INSTANCE = new NullValue();
10+
11+
static NullValue instance() {
12+
return INSTANCE;
13+
}
14+
15+
@Override
16+
public String toString() {
17+
return "null";
18+
}
19+
}

src/main/java/com/hubspot/jinjava/lib/tag/ForTag.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.hubspot.jinjava.interpret.InterpretException;
2828
import com.hubspot.jinjava.interpret.JinjavaInterpreter;
2929
import com.hubspot.jinjava.interpret.JinjavaInterpreter.InterpreterScopeClosable;
30+
import com.hubspot.jinjava.interpret.NullValue;
3031
import com.hubspot.jinjava.interpret.OutputTooBigException;
3132
import com.hubspot.jinjava.interpret.TemplateError;
3233
import com.hubspot.jinjava.interpret.TemplateSyntaxException;
@@ -200,7 +201,11 @@ public String renderForCollection(
200201

201202
// set item variables
202203
if (loopVars.size() == 1) {
203-
interpreter.getContext().put(loopVars.get(0), val);
204+
if (val == null && interpreter.getContext().get(loopVars.get(0)) != null) {
205+
interpreter.getContext().put(loopVars.get(0), NullValue.INSTANCE);
206+
} else {
207+
interpreter.getContext().put(loopVars.get(0), val);
208+
}
204209
} else {
205210
for (int loopVarIndex = 0; loopVarIndex < loopVars.size(); loopVarIndex++) {
206211
String loopVar = loopVars.get(loopVarIndex);

src/test/java/com/hubspot/jinjava/lib/tag/ForTagTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,18 @@ public void itAllowsCheckingOfWithinForLoop() throws NoSuchMethodException {
377377
assertThat(rendered.getOutput()).isEqualTo("false true true false");
378378
}
379379

380+
@Test
381+
public void forLoopWithNullValues() {
382+
context.put("number", -1);
383+
context.put("the_list", Lists.newArrayList(1L, 2L, null, null, null));
384+
TagNode tagNode = (TagNode) fixture("loop-last-var");
385+
Document dom = Jsoup.parseBodyFragment(tag.interpret(tagNode, interpreter));
386+
387+
assertThat(dom.select("h3")).hasSize(4);
388+
dom.outputSettings().prettyPrint(true).indentAmount(4);
389+
assertThat(dom.html()).contains("seven: null");
390+
}
391+
380392
public static boolean inForLoop() {
381393
JinjavaInterpreter interpreter = JinjavaInterpreter.getCurrent();
382394
return interpreter.getContext().isInForLoop();

0 commit comments

Comments
 (0)