@@ -1835,11 +1835,14 @@ private void populateMap(Object bean, Set<Object> objectsRecord, JSONParserConfi
18351835 Class <?> klass = bean .getClass ();
18361836
18371837 // If klass is a System class then set includeSuperClass to false.
1838+
1839+ // Check if this is a Java record type
1840+ boolean isRecord = isRecordType (klass );
18381841
18391842 Method [] methods = getMethods (klass );
18401843 for (final Method method : methods ) {
18411844 if (isValidMethod (method )) {
1842- final String key = getKeyNameFromMethod (method );
1845+ final String key = getKeyNameFromMethod (method , isRecord );
18431846 if (key != null && !key .isEmpty ()) {
18441847 processMethod (bean , objectsRecord , jsonParserConfiguration , method , key );
18451848 }
@@ -1885,6 +1888,29 @@ private void processMethod(Object bean, Set<Object> objectsRecord, JSONParserCon
18851888 }
18861889 }
18871890
1891+ /**
1892+ * Checks if a class is a Java record type.
1893+ * This uses reflection to check for the isRecord() method which was introduced in Java 16.
1894+ * This approach works even when running on Java 6+ JVM.
1895+ *
1896+ * @param klass the class to check
1897+ * @return true if the class is a record type, false otherwise
1898+ */
1899+ private static boolean isRecordType (Class <?> klass ) {
1900+ try {
1901+ // Use reflection to check if Class has an isRecord() method (Java 16+)
1902+ // This allows the code to compile on Java 6 while still detecting records at runtime
1903+ Method isRecordMethod = Class .class .getMethod ("isRecord" );
1904+ return (Boolean ) isRecordMethod .invoke (klass );
1905+ } catch (NoSuchMethodException e ) {
1906+ // isRecord() method doesn't exist - we're on Java < 16
1907+ return false ;
1908+ } catch (Exception e ) {
1909+ // Any other reflection error - assume not a record
1910+ return false ;
1911+ }
1912+ }
1913+
18881914 /**
18891915 * This is a convenience method to simplify populate maps
18901916 * @param klass the name of the object being checked
@@ -1901,7 +1927,7 @@ private static boolean isValidMethodName(String name) {
19011927 && !"getDeclaringClass" .equals (name );
19021928 }
19031929
1904- private static String getKeyNameFromMethod (Method method ) {
1930+ private static String getKeyNameFromMethod (Method method , boolean isRecordType ) {
19051931 final int ignoreDepth = getAnnotationDepth (method , JSONPropertyIgnore .class );
19061932 if (ignoreDepth > 0 ) {
19071933 final int forcedNameDepth = getAnnotationDepth (method , JSONPropertyName .class );
@@ -1922,12 +1948,9 @@ private static String getKeyNameFromMethod(Method method) {
19221948 } else if (name .startsWith ("is" ) && name .length () > 2 ) {
19231949 key = name .substring (2 );
19241950 } else {
1925- // Check if this is a record-style accessor (no prefix)
1926- // Record accessors are simple method names that match field names
1927- // They must start with a lowercase letter and should be declared in the class itself
1928- // (not inherited from Object, Enum, Number, or any java.* class)
1929- // Also exclude common Object/bean method names
1930- if (isRecordStyleAccessor (name , method )) {
1951+ // Only check for record-style accessors if this is actually a record type
1952+ // This maintains backward compatibility - classes with lowercase methods won't be affected
1953+ if (isRecordType && isRecordStyleAccessor (name , method )) {
19311954 return name ;
19321955 }
19331956 return null ;
0 commit comments