Skip to content

Commit ac2a063

Browse files
committed
Use single quote char for pyish serialization
1 parent 0959806 commit ac2a063

7 files changed

Lines changed: 38 additions & 17 deletions

File tree

pom.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@
6161
<dependency>
6262
<groupId>com.fasterxml.jackson.core</groupId>
6363
<artifactId>jackson-annotations</artifactId>
64-
<!--Using 2.12.6 instead of 2.13 https://github.com/FasterXML/jackson-databind/issues/3380#issuecomment-1018129505-->
6564
<version>2.12.6</version>
6665
</dependency>
6766
<dependency>

src/main/java/com/hubspot/jinjava/objects/date/PyishDate.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.hubspot.jinjava.interpret.JinjavaInterpreter;
44
import com.hubspot.jinjava.objects.PyWrapper;
5+
import com.hubspot.jinjava.objects.serialization.PyishObjectMapper;
56
import com.hubspot.jinjava.objects.serialization.PyishSerializable;
67
import java.io.Serializable;
78
import java.time.Instant;
@@ -149,9 +150,9 @@ public boolean equals(Object obj) {
149150
@Override
150151
public String toPyishString() {
151152
return String.format(
152-
"\"%s\"|strtotime(\"%s\")",
153+
"'%s'|strtotime(%s)",
153154
strftime(FULL_DATE_FORMAT),
154-
FULL_DATE_FORMAT
155+
PyishObjectMapper.getAsPyishString(FULL_DATE_FORMAT)
155156
);
156157
}
157158
}

src/main/java/com/hubspot/jinjava/objects/serialization/PyishCharacterEscapes.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.fasterxml.jackson.core.SerializableString;
44
import com.fasterxml.jackson.core.io.CharacterEscapes;
5+
import com.fasterxml.jackson.core.io.SerializedString;
56
import java.util.Arrays;
67

78
public class PyishCharacterEscapes extends CharacterEscapes {
@@ -11,9 +12,11 @@ public class PyishCharacterEscapes extends CharacterEscapes {
1112
private PyishCharacterEscapes() {
1213
int[] escapes = CharacterEscapes.standardAsciiEscapesForJSON();
1314
escapes['\n'] = CharacterEscapes.ESCAPE_NONE;
15+
escapes['"'] = CharacterEscapes.ESCAPE_NONE;
1416
escapes['\t'] = CharacterEscapes.ESCAPE_NONE;
1517
escapes['\r'] = CharacterEscapes.ESCAPE_NONE;
1618
escapes['\f'] = CharacterEscapes.ESCAPE_NONE;
19+
escapes['\''] = CharacterEscapes.ESCAPE_CUSTOM;
1720
asciiEscapes = escapes;
1821
}
1922

@@ -23,7 +26,10 @@ public int[] getEscapeCodesForAscii() {
2326
}
2427

2528
@Override
26-
public SerializableString getEscapeSequence(int i) {
29+
public SerializableString getEscapeSequence(int ch) {
30+
if (ch == '\'') {
31+
return new SerializedString("\\'");
32+
}
2733
return null;
2834
}
2935
}

src/main/java/com/hubspot/jinjava/objects/serialization/PyishObjectMapper.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.hubspot.jinjava.objects.serialization;
22

3+
import com.fasterxml.jackson.core.JsonFactoryBuilder;
34
import com.fasterxml.jackson.core.JsonGenerator;
45
import com.fasterxml.jackson.core.JsonProcessingException;
56
import com.fasterxml.jackson.databind.JsonSerializer;
@@ -18,7 +19,9 @@ public class PyishObjectMapper {
1819
public static final ObjectWriter PYISH_OBJECT_WRITER;
1920

2021
static {
21-
ObjectMapper mapper = new ObjectMapper()
22+
ObjectMapper mapper = new ObjectMapper(
23+
new JsonFactoryBuilder().quoteChar('\'').build()
24+
)
2225
.registerModule(
2326
new SimpleModule()
2427
.setSerializerModifier(PyishBeanSerializerModifier.INSTANCE)
@@ -54,14 +57,10 @@ public static String getAsPyishStringOrThrow(Object val)
5457
if (maxStringLength.map(max -> string.length() > max).orElse(false)) {
5558
throw new OutputTooBigException(maxStringLength.get(), string.length());
5659
}
57-
String result = string
58-
.replace("'", "\\'")
59-
// Replace double-quotes with single quote as they are preferred in Jinja
60-
.replaceAll("(?<!\\\\)(\\\\\\\\)*(?:\")", "$1'");
61-
if (!result.contains("{{")) {
62-
return String.join("} ", result.split("}(?=})"));
60+
if (string.contains("}}") && !string.contains("{{")) {
61+
return String.join("} ", string.split("}(?=})"));
6362
}
64-
return result;
63+
return string;
6564
}
6665

6766
public static class NullKeySerializer extends JsonSerializer<Object> {

src/main/java/com/hubspot/jinjava/objects/serialization/PyishSerializable.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package com.hubspot.jinjava.objects.serialization;
22

3+
import com.fasterxml.jackson.core.JsonFactoryBuilder;
34
import com.fasterxml.jackson.core.JsonProcessingException;
45
import com.fasterxml.jackson.databind.ObjectMapper;
56
import com.fasterxml.jackson.databind.ObjectWriter;
67
import com.hubspot.jinjava.objects.PyWrapper;
78
import java.util.Objects;
89

910
public interface PyishSerializable extends PyWrapper {
10-
ObjectWriter SELF_WRITER = new ObjectMapper()
11+
ObjectWriter SELF_WRITER = new ObjectMapper(
12+
new JsonFactoryBuilder().quoteChar('\'').build()
13+
)
1114
.writer(PyishPrettyPrinter.INSTANCE)
1215
.with(PyishCharacterEscapes.INSTANCE);
1316
/**
@@ -31,7 +34,7 @@ static String writeValueAsString(Object value) {
3134
try {
3235
return SELF_WRITER.writeValueAsString(value);
3336
} catch (JsonProcessingException e) {
34-
return '"' + Objects.toString(value) + '"';
37+
return '\'' + Objects.toString(value) + '\'';
3538
}
3639
}
3740
}

src/main/java/com/hubspot/jinjava/util/EagerReconstructionUtils.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ public static EagerExecutionResult executeInChildContext(
122122
.stream()
123123
.filter(entry -> initiallyResolvedHashes.containsKey(entry.getKey()))
124124
.filter(
125-
entry -> EagerExpressionResolver.isResolvableObject(entry.getValue(), 2, 20) // TODO make this configurable
125+
entry ->
126+
EagerExpressionResolver.isResolvableObject(entry.getValue(), 4, 400) // TODO make this configurable
126127
);
127128
} else {
128129
entryStream =
@@ -132,7 +133,8 @@ public static EagerExecutionResult executeInChildContext(
132133
.stream()
133134
.filter(entry -> initiallyResolvedHashes.containsKey(entry.getKey()))
134135
.filter(
135-
entry -> EagerExpressionResolver.isResolvableObject(entry.getValue(), 2, 20) // TODO make this configurable
136+
entry ->
137+
EagerExpressionResolver.isResolvableObject(entry.getValue(), 4, 400) // TODO make this configurable
136138
);
137139
}
138140
entryStream.forEach(

src/test/java/com/hubspot/jinjava/util/EagerExpressionResolverTest.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,18 @@ public void itSerializesDateProperly() {
310310
EagerExpressionResult eagerExpressionResult = eagerResolveExpression("date");
311311

312312
assertThat(WhitespaceUtils.unquoteAndUnescape(eagerExpressionResult.toString()))
313-
.isEqualTo(date.toPyishString().replace("'", "\\'").replace('"', '\''));
313+
.isEqualTo(date.toPyishString());
314+
interpreter.render(
315+
"{% set foo = " +
316+
PyishObjectMapper.getAsPyishString(ImmutableMap.of("a", date)) +
317+
" %}"
318+
);
319+
assertThat(
320+
(
321+
(PyishDate) ((Map<String, Object>) interpreter.getContext().get("foo")).get("a")
322+
).toDateTime()
323+
)
324+
.isEqualTo(date.toDateTime());
314325
}
315326

316327
@Test

0 commit comments

Comments
 (0)