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 af2471a267 YAML fix
af2471a267 is described below

commit af2471a267aac0523687c1b1c96ae0eefb980d26
Author: James Bognar <[email protected]>
AuthorDate: Wed Mar 18 18:47:27 2026 -0400

    YAML fix
---
 .../java/org/apache/juneau/yaml/YamlParser.java    |  4 ---
 .../org/apache/juneau/yaml/YamlParserSession.java  | 37 +++++++++++++---------
 .../juneau/a/rttests/RoundTripMaps_Test.java       |  2 --
 3 files changed, 22 insertions(+), 21 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlParser.java
index 4dfec79b32..6947d74823 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlParser.java
@@ -51,10 +51,6 @@ import org.apache.juneau.parser.*;
  *             those key types.  {@link java.util.LinkedHashMap LinkedHashMap} 
and {@link java.util.TreeMap TreeMap}
  *             with {@link String} keys work reliably.
  *     <li>
- *             {@link java.util.HashMap HashMap} instances that contain a 
{@code null} key can fail to round-trip in
- *             some cases; {@link java.util.LinkedHashMap LinkedHashMap} and 
{@link java.util.TreeMap TreeMap} handle
- *             null keys correctly.
- *     <li>
  *             No strict vs non-strict mode; unlike JSON, there is no 
equivalent to JSON's lax parsing of comments,
  *             unquoted attributes, or concatenated strings.
  *     <li>
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlParserSession.java
index b083a0ba9e..466d36082d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlParserSession.java
@@ -419,33 +419,24 @@ public class YamlParserSession extends 
ReaderParserSession {
                if (s.isEmpty())
                        return null;
 
-               if ("null".equals(s))
-                       return null;
-
-               if ("true".equals(s) || "false".equals(s)) {
-                       if (sType.isObject() || sType.isBoolean())
-                               return Boolean.valueOf(s);
-                       return convertToType(s, sType, eType, outer, pMeta);
-               }
-
                if (looksLikeMappingKey(r)) {
                        r.read(); // consume ':'
                        int cp = r.peek();
                        if (cp == ' ')
                                r.read(); // consume space after ':'
 
+                       String keyStr = isYamlNull(s) ? null : trim(s);
                        if (sType.isObject()) {
                                var m2 = new JsonMap(this);
                                Object value = parseAnything(object(), r, m2, 
pMeta);
-                               String ts = trim(s);
-                               setName(object(), value, ts);
-                               m2.put(ts, value);
+                               setName(object(), value, keyStr);
+                               m2.put(keyStr, value);
                                parseBlockMappingRemainder(r, m2, string(), 
object(), pMeta, keyIndent);
                                return cast(m2, pMeta, eType);
                        } else if (sType.isMap()) {
                                Map m = (sType.canCreateNewInstance(outer) ? 
(Map)sType.newInstance(outer) : newGenericMap(sType));
                                Object value = 
parseAnything(sType.getValueType(), r, m, pMeta);
-                               Object key = convertAttrToType(m, trim(s), 
sType.getKeyType());
+                               Object key = convertAttrToType(m, keyStr, 
sType.getKeyType());
                                setName(sType.getValueType(), value, key);
                                m.put(key, value);
                                parseBlockMappingRemainder(r, m, 
sType.getKeyType(), sType.getValueType(), pMeta, keyIndent);
@@ -473,6 +464,15 @@ public class YamlParserSession extends ReaderParserSession 
{
                        }
                }
 
+               if (isYamlNull(s))
+                       return null;
+
+               if ("true".equals(s) || "false".equals(s)) {
+                       if (sType.isObject() || sType.isBoolean())
+                               return Boolean.valueOf(s);
+                       return convertToType(s, sType, eType, outer, pMeta);
+               }
+
                return convertToType(s, sType, eType, outer, pMeta);
        }
 
@@ -503,6 +503,10 @@ public class YamlParserSession extends ReaderParserSession 
{
                return r.peek() == ':';
        }
 
+       private static boolean isYamlNull(String s) {
+               return "null".equals(s) || "Null".equals(s) || "NULL".equals(s) 
|| "~".equals(s);
+       }
+
        private <K,V> void parseBlockMappingRemainder(ParserReader r, Map<K,V> 
m, ClassMeta<K> keyType, ClassMeta<V> valueType, BeanPropertyMeta pMeta, int 
parentIndent) throws IOException, ParseException, ExecutableException {
                parseBlockMapping(r, m, keyType, valueType, pMeta, 
parentIndent);
        }
@@ -661,7 +665,10 @@ public class YamlParserSession extends ReaderParserSession 
{
                        return parseSingleQuotedString(r);
                if (c == '"')
                        return parseDoubleQuotedString(r);
-               return parsePlainFlowKey(r);
+               var key = parsePlainFlowKey(r);
+               if (isYamlNull(key))
+                       return null;
+               return key;
        }
 
        private static String parsePlainFlowKey(ParserReader r) throws 
IOException {
@@ -853,7 +860,7 @@ public class YamlParserSession extends ReaderParserSession {
                        }
                }
                String key = sb.toString().trim();
-               if ("null".equals(key) || "Null".equals(key) || 
"NULL".equals(key) || "~".equals(key))
+               if (isYamlNull(key))
                        return null;
                return key;
        }
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/RoundTripMaps_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/RoundTripMaps_Test.java
index 8bf02a5696..a2f60703ea 100755
--- 
a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/RoundTripMaps_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/RoundTripMaps_Test.java
@@ -174,8 +174,6 @@ class RoundTripMaps_Test extends TestBase {
                tester(29, "Yaml - default")
                        
.serializer(YamlSerializer.create().keepNullProperties().addBeanTypes().addRootType())
                        .parser(YamlParser.create())
-                       // TODO: Revisit when YamlParser round-trips HashMap 
with null keys (see YamlParser javadoc)
-                       .skipIf(HashMap.class::isInstance)
                        .build(),
                tester(30, "Toml - default")
                        .serializer(TomlSerializer.create())

Reply via email to