This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new adc877845b Parquet fix
adc877845b is described below
commit adc877845bc54df345e279d9533308f317fe8644
Author: James Bognar <[email protected]>
AuthorDate: Wed Mar 18 20:30:39 2026 -0400
Parquet fix
---
.../juneau/markdown/MarkdownParserSession.java | 8 +++--
.../org/apache/juneau/parquet/ParquetParser.java | 5 ++++
.../juneau/parquet/ParquetParserSession.java | 33 ++++++++++++--------
.../apache/juneau/parquet/ParquetSerializer.java | 5 ++++
.../juneau/parquet/ParquetSerializerSession.java | 6 ++--
.../a/rttests/TrimStrings_RoundTripTest.java | 35 ++++++++++------------
6 files changed, 56 insertions(+), 36 deletions(-)
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/markdown/MarkdownParserSession.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/markdown/MarkdownParserSession.java
index bc974776d3..a8ceb87b17 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/markdown/MarkdownParserSession.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/markdown/MarkdownParserSession.java
@@ -593,8 +593,12 @@ public class MarkdownParserSession extends
ReaderParserSession {
* Returns a Json5Parser that shares this session's bean context
(swaps, implClasses, dictionary).
*/
private JsonParser getJson5Parser() {
- if (json5Parser == null)
- json5Parser =
Json5Parser.create().beanContext((BeanContext) getContext()).build();
+ if (json5Parser == null) {
+ var b = Json5Parser.create().beanContext((BeanContext)
getContext());
+ if (isTrimStrings())
+ b = b.trimStrings();
+ json5Parser = b.build();
+ }
return json5Parser;
}
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetParser.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetParser.java
index 346f4dec75..cbf3399173 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetParser.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetParser.java
@@ -128,6 +128,11 @@ public class ParquetParser extends InputStreamParser
implements ParquetMetaProvi
nullKeyString = builder.nullKeyString;
}
+ @Override /* Overridden from Context */
+ public Builder copy() {
+ return new Builder(this);
+ }
+
@Override
public ParquetParserSession.Builder createSession() {
return ParquetParserSession.create(this);
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetParserSession.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetParserSession.java
index c282ad3e9a..995a648d58 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetParserSession.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetParserSession.java
@@ -446,12 +446,13 @@ public class ParquetParserSession extends
InputStreamParserSession {
for (var cc : firstGroup.columns()) {
var path = String.join(".", cc.pathInSchema());
List<Object> values;
+ var trim = isTrimStrings();
if (isListColumnPath(path))
- values = readListColumnChunk(fileBytes, cc,
numRows);
+ values = readListColumnChunk(fileBytes, cc,
numRows, trim);
else if (isMapKeyValueColumnPath(path))
- values = readMapKeyValueColumnChunk(fileBytes,
cc, numRows);
+ values = readMapKeyValueColumnChunk(fileBytes,
cc, numRows, trim);
else
- values = readColumnChunk(fileBytes, cc,
numRows, schemaRepetition);
+ values = readColumnChunk(fileBytes, cc,
numRows, schemaRepetition, trim);
columnData.put(path, values);
}
if (parquetDebug()) {
@@ -507,7 +508,7 @@ public class ParquetParserSession extends
InputStreamParserSession {
return idx < 0 ? listColumnPath : listColumnPath.substring(0,
idx);
}
- private static List<Object> readListColumnChunk(byte[] fileBytes,
ColumnChunkMeta cc, int numRows) throws ParseException {
+ private static List<Object> readListColumnChunk(byte[] fileBytes,
ColumnChunkMeta cc, int numRows, boolean trimStrings) throws ParseException {
try {
var path = String.join(".", cc.pathInSchema());
var rowRelPath = rowRelativePath(path);
@@ -584,7 +585,7 @@ public class ParquetParserSession extends
InputStreamParserSession {
int def = defDecoder.readInt();
Object val;
if (def >= maxDef) {
- val = readValue(valueReader, cc.type());
+ val = readValue(valueReader, cc.type(),
trimStrings);
} else {
val = null;
}
@@ -710,7 +711,7 @@ public class ParquetParserSession extends
InputStreamParserSession {
private static final int MAP_MAX_DEF = 2;
private static final int MAP_MAX_REP = 1;
- private static List<Object> readMapKeyValueColumnChunk(byte[]
fileBytes, ColumnChunkMeta cc, int numRows) throws ParseException {
+ private static List<Object> readMapKeyValueColumnChunk(byte[]
fileBytes, ColumnChunkMeta cc, int numRows, boolean trimStrings) throws
ParseException {
try {
int maxDef = MAP_MAX_DEF;
int maxRep = MAP_MAX_REP;
@@ -783,7 +784,7 @@ public class ParquetParserSession extends
InputStreamParserSession {
int def = defDecoder.readInt();
Object val;
if (def >= maxDef) {
- val = readValue(valueReader, cc.type());
+ val = readValue(valueReader, cc.type(),
trimStrings);
} else {
val = null;
}
@@ -827,7 +828,7 @@ public class ParquetParserSession extends
InputStreamParserSession {
return result;
}
- private static List<Object> readColumnChunk(byte[] fileBytes,
ColumnChunkMeta cc, int numRows, Map<String, Integer> schemaRepetition) throws
ParseException {
+ private static List<Object> readColumnChunk(byte[] fileBytes,
ColumnChunkMeta cc, int numRows, Map<String, Integer> schemaRepetition, boolean
trimStrings) throws ParseException {
try {
int off = (int)cc.dataPageOffset();
var bais = new ByteArrayInputStream(fileBytes, off,
fileBytes.length - off);
@@ -876,7 +877,7 @@ public class ParquetParserSession extends
InputStreamParserSession {
var reader = new ParquetColumnReader(decompressed,
valuesToRead, maxDefLevel);
var values = new ArrayList<>();
while (reader.hasNext()) {
- values.add(readValue(reader, cc.type()));
+ values.add(readValue(reader, cc.type(),
trimStrings));
}
if (parquetDebug())
parquetDebugLog("readColumnChunk values: path="
+ path + " values=" + values);
@@ -886,7 +887,7 @@ public class ParquetParserSession extends
InputStreamParserSession {
}
}
- private static Object readValue(ParquetColumnReader reader, int type)
throws IOException {
+ private static Object readValue(ParquetColumnReader reader, int type,
boolean trimStrings) throws IOException {
reader.advance();
if (reader.isNull())
return null;
@@ -896,9 +897,15 @@ public class ParquetParserSession extends
InputStreamParserSession {
case TYPE_INT64 -> reader.readInt64();
case TYPE_FLOAT -> reader.readFloat();
case TYPE_DOUBLE -> reader.readDouble();
- case TYPE_BYTE_ARRAY -> reader.readByteArrayAsString();
+ case TYPE_BYTE_ARRAY -> {
+ var s = reader.readByteArrayAsString();
+ yield trimStrings && s != null ? s.trim() : s;
+ }
case TYPE_FIXED_LEN_BYTE_ARRAY ->
reader.readFixedLenByteArray(16);
- default -> reader.readByteArrayAsString();
+ default -> {
+ var s = reader.readByteArrayAsString();
+ yield trimStrings && s != null ? s.trim() : s;
+ }
};
}
@@ -917,6 +924,8 @@ public class ParquetParserSession extends
InputStreamParserSession {
var values = e.getValue();
var v = i < values.size() ? values.get(i) :
null;
var path = isListColumnPath(fullPath) ?
listProp : rowRelPath;
+ if (isTrimStrings())
+ path = path.trim();
setByPath(row, path, v);
}
for (var e : listBeanColumns.entrySet()) {
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetSerializer.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetSerializer.java
index 305650d66e..254a613acb 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetSerializer.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetSerializer.java
@@ -239,6 +239,11 @@ public class ParquetSerializer extends
OutputStreamSerializer implements Parquet
nullKeyString = builder.nullKeyString;
}
+ @Override /* Overridden from Context */
+ public Builder copy() {
+ return new Builder(this);
+ }
+
@Override
public ParquetSerializerSession.Builder createSession() {
return ParquetSerializerSession.create(this);
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetSerializerSession.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetSerializerSession.java
index 5cb13867e9..66db8fa731 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetSerializerSession.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetSerializerSession.java
@@ -194,7 +194,7 @@ public class ParquetSerializerSession extends
OutputStreamSerializerSession {
// Replace null keys with the null-key sentinel
so they survive as a named column in the schema.
var swappedMap = new LinkedHashMap<>();
for (var e : m.entrySet()) {
- var key = e.getKey() == null ?
ctx.nullKeyString : e.getKey();
+ var key = e.getKey() == null ?
ctx.nullKeyString : trim(e.getKey());
var val = e.getValue();
if (val != null)
val = applySwap(val,
getClassMetaForObject(val));
@@ -444,7 +444,7 @@ public class ParquetSerializerSession extends
OutputStreamSerializerSession {
}
if (key instanceof Enum<?> e)
return ctx.getBeanContext().isUseEnumNames() ? e.name()
: e.toString();
- return String.valueOf(generalize(key,
getClassMetaForObject(key)));
+ return trim(String.valueOf(generalize(key,
getClassMetaForObject(key))));
}
private List<FlattenedEntry> extractFlattenedListValues(List<?> rows,
String path) throws SerializeException {
@@ -735,7 +735,7 @@ public class ParquetSerializerSession extends
OutputStreamSerializerSession {
if (v instanceof byte[] b)
return b;
if (v instanceof String s)
- return s.getBytes(StandardCharsets.UTF_8);
+ return trim(s).getBytes(StandardCharsets.UTF_8);
if (v instanceof Enum<?> e)
return (ctx.getBeanContext().isUseEnumNames() ?
e.name() : e.toString()).getBytes(StandardCharsets.UTF_8);
if (v instanceof Duration d)
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/TrimStrings_RoundTripTest.java
b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/TrimStrings_RoundTripTest.java
index da81f4307e..63070cda83 100755
---
a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/TrimStrings_RoundTripTest.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/TrimStrings_RoundTripTest.java
@@ -21,7 +21,6 @@ import static
org.apache.juneau.commons.utils.CollectionUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import org.apache.juneau.collections.*;
-import org.apache.juneau.markdown.*;
import org.apache.juneau.parquet.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.serializer.*;
@@ -42,12 +41,6 @@ class TrimStrings_RoundTripTest extends RoundTripTest_Base {
void a01_basic(RoundTrip_Tester t) throws Exception {
if (t.isValidationOnly())
return;
- // TODO - Skip Markdown - inline JSON5 trimStrings behavior
needs investigation
- if (t.getSerializer() instanceof MarkdownSerializer)
- return;
- // TODO - Skip Parquet - copy() returns Serializer.Builder
incompatible with ParquetSerializer constructor
- if (t.getSerializer() instanceof ParquetSerializer)
- return;
var s = t.getSerializer();
var p = t.getParser();
@@ -68,19 +61,23 @@ class TrimStrings_RoundTripTest extends RoundTripTest_Base {
a = p2.parse(s.serialize(in), JsonMap.class);
assertEquals(json(a), json(e));
- in = new JsonList("[' foo ', {' foo ': ' bar '}]");
- e = new JsonList("['foo',{foo:'bar'}]");
- a = p.parse(s2.serialize(in), JsonList.class);
- assertEquals(json(a), json(e));
- a = p2.parse(s.serialize(in), JsonList.class);
- assertEquals(json(a), json(e));
+ // Skip Parquet for mixed-type JsonList and bean with
JsonList/JsonMap properties.
+ // Parquet's static schema cannot represent mixed-type
collections (string + map in same list).
+ if (!(s instanceof ParquetSerializer)) {
+ in = new JsonList("[' foo ', {' foo ': ' bar '}]");
+ e = new JsonList("['foo',{foo:'bar'}]");
+ a = p.parse(s2.serialize(in), JsonList.class);
+ assertEquals(json(a), json(e));
+ a = p2.parse(s.serialize(in), JsonList.class);
+ assertEquals(json(a), json(e));
- in = new A().init1();
- e = new A().init2();
- a = p.parse(s2.serialize(in), A.class);
- assertEquals(json(a), json(e));
- a = p2.parse(s.serialize(in), A.class);
- assertEquals(json(a), json(e));
+ in = new A().init1();
+ e = new A().init2();
+ a = p.parse(s2.serialize(in), A.class);
+ assertEquals(json(a), json(e));
+ a = p2.parse(s.serialize(in), A.class);
+ assertEquals(json(a), json(e));
+ }
}
public static class A {