diff --git a/spring-core/src/main/java/org/springframework/aot/nativex/BasicJsonWriter.java b/spring-core/src/main/java/org/springframework/aot/nativex/BasicJsonWriter.java index 4fa022252ae..3f2a039ce69 100644 --- a/spring-core/src/main/java/org/springframework/aot/nativex/BasicJsonWriter.java +++ b/spring-core/src/main/java/org/springframework/aot/nativex/BasicJsonWriter.java @@ -23,6 +23,9 @@ import java.util.List; import java.util.Map; import java.util.function.Consumer; +import org.springframework.aot.hint.TypeReference; +import org.springframework.lang.Nullable; + /** * Very basic json writer for the purposes of translating runtime hints to native * configuration. @@ -129,6 +132,9 @@ class BasicJsonWriter { else if (value instanceof List list) { writeArray(list, false); } + else if (value instanceof TypeReference typeReference) { + this.writer.print(quote(toName(typeReference))); + } else if (value instanceof CharSequence string) { this.writer.print(quote(escape(string))); } @@ -144,6 +150,22 @@ class BasicJsonWriter { return "\"" + name + "\""; } + private String toName(TypeReference typeReference) { + StringBuilder names = new StringBuilder(); + buildName(typeReference, names); + return typeReference.getPackageName() + "." + names; + } + + private void buildName(@Nullable TypeReference type, StringBuilder sb) { + if (type == null) { + return; + } + String typeName = (type.getEnclosingType() != null) ? "$" + type.getSimpleName() : type.getSimpleName(); + sb.insert(0, typeName); + buildName(type.getEnclosingType(), sb); + } + + private static String escape(CharSequence input) { StringBuilder builder = new StringBuilder(); input.chars().forEach(c -> { diff --git a/spring-core/src/main/java/org/springframework/aot/nativex/JavaSerializationHintsWriter.java b/spring-core/src/main/java/org/springframework/aot/nativex/JavaSerializationHintsWriter.java index cebea99397c..106801070f7 100644 --- a/spring-core/src/main/java/org/springframework/aot/nativex/JavaSerializationHintsWriter.java +++ b/spring-core/src/main/java/org/springframework/aot/nativex/JavaSerializationHintsWriter.java @@ -42,7 +42,7 @@ class JavaSerializationHintsWriter { private Map toAttributes(TypeReference typeReference) { LinkedHashMap attributes = new LinkedHashMap<>(); - attributes.put("name", typeReference.getCanonicalName()); + attributes.put("name", typeReference); return attributes; } diff --git a/spring-core/src/main/java/org/springframework/aot/nativex/ReflectionHintsWriter.java b/spring-core/src/main/java/org/springframework/aot/nativex/ReflectionHintsWriter.java index 09c8dd09d14..ae1041e422a 100644 --- a/spring-core/src/main/java/org/springframework/aot/nativex/ReflectionHintsWriter.java +++ b/spring-core/src/main/java/org/springframework/aot/nativex/ReflectionHintsWriter.java @@ -52,7 +52,7 @@ class ReflectionHintsWriter { private Map toAttributes(TypeHint hint) { Map attributes = new LinkedHashMap<>(); - attributes.put("name", hint.getType().getCanonicalName()); + attributes.put("name", hint.getType()); handleCondition(attributes, hint); handleCategories(attributes, hint.getMemberCategories()); handleFields(attributes, hint.fields()); @@ -63,7 +63,7 @@ class ReflectionHintsWriter { private void handleCondition(Map attributes, TypeHint hint) { if (hint.getReachableType() != null) { Map conditionAttributes = new LinkedHashMap<>(); - conditionAttributes.put("typeReachable", hint.getReachableType().getCanonicalName()); + conditionAttributes.put("typeReachable", hint.getReachableType()); attributes.put("condition", conditionAttributes); } } diff --git a/spring-core/src/test/java/org/springframework/aot/nativex/BasicJsonWriterTests.java b/spring-core/src/test/java/org/springframework/aot/nativex/BasicJsonWriterTests.java index 4545c9caa9c..5a543dafb5a 100644 --- a/spring-core/src/test/java/org/springframework/aot/nativex/BasicJsonWriterTests.java +++ b/spring-core/src/test/java/org/springframework/aot/nativex/BasicJsonWriterTests.java @@ -24,6 +24,9 @@ import java.util.Map; import org.junit.jupiter.api.Test; +import org.springframework.aot.hint.TypeReference; +import org.springframework.aot.nativex.BasicJsonWriterTests.Nested.Inner; + import static org.assertj.core.api.Assertions.assertThat; /** @@ -136,49 +139,66 @@ class BasicJsonWriterTests { @Test void writeWithEscapeDoubleQuote() { - assertEscapedValue("foo\"bar", "foo\\\"bar"); + assertStringAttribute("foo\"bar", "foo\\\"bar"); } @Test void writeWithEscapeBackslash() { - assertEscapedValue("foo\"bar", "foo\\\"bar"); + assertStringAttribute("foo\"bar", "foo\\\"bar"); } @Test void writeWithEscapeBackspace() { - assertEscapedValue("foo\bbar", "foo\\bbar"); + assertStringAttribute("foo\bbar", "foo\\bbar"); } @Test void writeWithEscapeFormFeed() { - assertEscapedValue("foo\fbar", "foo\\fbar"); + assertStringAttribute("foo\fbar", "foo\\fbar"); } @Test void writeWithEscapeNewline() { - assertEscapedValue("foo\nbar", "foo\\nbar"); + assertStringAttribute("foo\nbar", "foo\\nbar"); } @Test void writeWithEscapeCarriageReturn() { - assertEscapedValue("foo\rbar", "foo\\rbar"); + assertStringAttribute("foo\rbar", "foo\\rbar"); } @Test void writeWithEscapeTab() { - assertEscapedValue("foo\tbar", "foo\\tbar"); + assertStringAttribute("foo\tbar", "foo\\tbar"); } @Test void writeWithEscapeUnicode() { - assertEscapedValue("foo\u001Fbar", "foo\\u001fbar"); + assertStringAttribute("foo\u001Fbar", "foo\\u001fbar"); } - void assertEscapedValue(String value, String expectedEscapedValue) { + @Test + void writeWithTypeReferenceForSimpleClass() { + assertStringAttribute(TypeReference.of(String.class), "java.lang.String"); + } + + @Test + void writeWithTypeReferenceForInnerClass() { + assertStringAttribute(TypeReference.of(Nested.class), + "org.springframework.aot.nativex.BasicJsonWriterTests$Nested"); + } + + @Test + void writeWithTypeReferenceForDoubleInnerClass() { + assertStringAttribute(TypeReference.of(Inner.class), + "org.springframework.aot.nativex.BasicJsonWriterTests$Nested$Inner"); + } + + void assertStringAttribute(Object value, String expectedValue) { Map attributes = new LinkedHashMap<>(); attributes.put("test", value); this.json.writeObject(attributes); - assertThat(out.toString()).contains("\"test\": \"" + expectedEscapedValue + "\""); + assertThat(out.toString()).contains("\"test\": \"" + expectedValue + "\""); } private static LinkedHashMap orderedMap(String key, Object value) { @@ -187,4 +207,12 @@ class BasicJsonWriterTests { return map; } + + static class Nested { + + static class Inner { + + } + } + }