@@ -376,9 +376,10 @@ private ExprValue parseStruct(Content content, String prefix, boolean supportArr
376376 entry ->
377377 populateValueRecursive (
378378 result ,
379- // Use literal() because entry.getKey() is a JSON field name where dots are
380- // literal characters, not path separators (e.g., ".", "..", "a...", ".a")
381- JsonPath .literal (entry .getKey ()),
379+ // Use fromPath() to split dot-separated field names into nested paths
380+ // (e.g., "log.json" -> ["log", "json"] for flattening support).
381+ // fromPath() handles edge cases like "." or ".." that would otherwise crash.
382+ JsonPath .fromPath (entry .getKey ()),
382383 parse (
383384 entry .getValue (),
384385 makeField (prefix , entry .getKey ()),
@@ -429,11 +430,34 @@ public static JsonPath literal(String fieldName) {
429430 * Create a JsonPath by splitting a dot-separated path into components. Use this when the path
430431 * represents a nested field structure (e.g., "log.json.time" → ["log", "json", "time"]).
431432 *
433+ * <p>Handles edge cases:
434+ *
435+ * <ul>
436+ * <li>Dot-only field names like "." or ".." - split returns empty array, use literal
437+ * <li>Leading/trailing/consecutive dots like ".a", "a.", "a..b" - split produces empty
438+ * strings, use literal to avoid creating nested structures with empty keys
439+ * </ul>
440+ *
432441 * @param path The dot-separated path
433- * @return A JsonPath with components split by dots
442+ * @return A JsonPath with components split by dots, or literal if splitting would produce empty
443+ * keys
434444 */
435445 public static JsonPath fromPath (String path ) {
436- return new JsonPath (List .of (path .split ("\\ ." )));
446+ // Use -1 limit to preserve trailing empty strings (e.g., "a..." -> ["a", "", "", ""])
447+ String [] parts = path .split ("\\ ." , -1 );
448+ // Handle edge cases where splitting would produce problematic results:
449+ // 1. Empty array (dot-only field names like "." or "..")
450+ // 2. Array with empty strings (e.g., ".a" -> ["", "a"], "a..." -> ["a", "", "", ""])
451+ // In these cases, treat the original string as a literal field name
452+ if (parts .length == 0 ) {
453+ return new JsonPath (List .of (path ));
454+ }
455+ for (String part : parts ) {
456+ if (part .isEmpty ()) {
457+ return new JsonPath (List .of (path ));
458+ }
459+ }
460+ return new JsonPath (List .of (parts ));
437461 }
438462
439463 private JsonPath (List <String > paths ) {
0 commit comments