From f6f356396e82cf6a73f6c6b7ad25bbd81cadc424 Mon Sep 17 00:00:00 2001 From: Chris Chua Date: Tue, 25 Oct 2022 18:01:58 +0800 Subject: [PATCH 1/3] add support for numeric keys in dictionary This is a hack to support numeric keys declared in map literals. Most of such usages typically use the keys as if they were strings, so this hack is likely safe. A hack is used as opposed to overhauling all maps used since full support would require overhauling all maps types to `Map` which seems overkill. --- src/main/java/com/hubspot/jinjava/el/ext/AstDict.java | 6 ++++++ .../com/hubspot/jinjava/el/ExtendedSyntaxBuilderTest.java | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/main/java/com/hubspot/jinjava/el/ext/AstDict.java b/src/main/java/com/hubspot/jinjava/el/ext/AstDict.java index 938449834..8046527b9 100644 --- a/src/main/java/com/hubspot/jinjava/el/ext/AstDict.java +++ b/src/main/java/com/hubspot/jinjava/el/ext/AstDict.java @@ -7,6 +7,7 @@ import de.odysseus.el.tree.impl.ast.AstIdentifier; import de.odysseus.el.tree.impl.ast.AstLiteral; import de.odysseus.el.tree.impl.ast.AstNode; +import de.odysseus.el.tree.impl.ast.AstNumber; import de.odysseus.el.tree.impl.ast.AstString; import java.util.LinkedHashMap; import java.util.Map; @@ -45,6 +46,11 @@ public Object eval(Bindings bindings, ELContext context) { } else { key = ((AstIdentifier) entryKey).getName(); } + } else if (entryKey instanceof AstNumber) { + // This is a hack to treat numeric keys as string keys in the dictionary. + // In most cases this is adequate since the keys are typically treated as + // strings. + key = entryKey.eval(bindings, context).toString(); } else { throw new TemplateStateException( "Dict key must be a string or identifier, was: " + entryKey diff --git a/src/test/java/com/hubspot/jinjava/el/ExtendedSyntaxBuilderTest.java b/src/test/java/com/hubspot/jinjava/el/ExtendedSyntaxBuilderTest.java index c3e9d49fe..6594ce24b 100644 --- a/src/test/java/com/hubspot/jinjava/el/ExtendedSyntaxBuilderTest.java +++ b/src/test/java/com/hubspot/jinjava/el/ExtendedSyntaxBuilderTest.java @@ -187,6 +187,11 @@ public void complexMapLiteral() { assertThat((Map) map.get("Boston")).contains(entry("city", "Boston")); } + @Test + public void mapLiteralWithNumericKey() { + assertThat((Map) val("{0:'test'}")).contains(entry("0", "test")); + } + @Test public void itParsesDictWithVariableRefs() { List theList = Lists.newArrayList(1L, 2L, 3L); From 2335c05c05f669d00be9b7f557ebac25b501f76a Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Tue, 30 Jan 2024 14:37:23 -0700 Subject: [PATCH 2/3] update error message for dict keys --- src/main/java/com/hubspot/jinjava/el/ext/AstDict.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/hubspot/jinjava/el/ext/AstDict.java b/src/main/java/com/hubspot/jinjava/el/ext/AstDict.java index 8046527b9..a2181659c 100644 --- a/src/main/java/com/hubspot/jinjava/el/ext/AstDict.java +++ b/src/main/java/com/hubspot/jinjava/el/ext/AstDict.java @@ -53,7 +53,7 @@ public Object eval(Bindings bindings, ELContext context) { key = entryKey.eval(bindings, context).toString(); } else { throw new TemplateStateException( - "Dict key must be a string or identifier, was: " + entryKey + "Dict key must be a string, or identifier, or a number, was: " + entryKey ); } From 5259a8d82e5a4b00664a8ad6de7a99d99c82bfae Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Fri, 22 Mar 2024 12:41:39 -0600 Subject: [PATCH 3/3] use Objects.toString for null safety --- src/main/java/com/hubspot/jinjava/el/ext/AstDict.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/hubspot/jinjava/el/ext/AstDict.java b/src/main/java/com/hubspot/jinjava/el/ext/AstDict.java index a2181659c..01e626bf6 100644 --- a/src/main/java/com/hubspot/jinjava/el/ext/AstDict.java +++ b/src/main/java/com/hubspot/jinjava/el/ext/AstDict.java @@ -50,7 +50,7 @@ public Object eval(Bindings bindings, ELContext context) { // This is a hack to treat numeric keys as string keys in the dictionary. // In most cases this is adequate since the keys are typically treated as // strings. - key = entryKey.eval(bindings, context).toString(); + key = Objects.toString(entryKey.eval(bindings, context)); } else { throw new TemplateStateException( "Dict key must be a string, or identifier, or a number, was: " + entryKey