Skip to content

Commit 0f8959e

Browse files
committed
Polish BeanOutputConverter and associated tests
Signed-off-by: Nicolas Krier <[email protected]>
1 parent a8d2208 commit 0f8959e

File tree

9 files changed

+29
-39
lines changed

9 files changed

+29
-39
lines changed

spring-ai-model/src/main/java/org/springframework/ai/converter/BeanOutputConverter.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2024 the original author or authors.
2+
* Copyright 2023-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
2121
import java.util.Objects;
2222

2323
import com.fasterxml.jackson.core.JsonProcessingException;
24+
import com.fasterxml.jackson.core.type.TypeReference;
2425
import com.fasterxml.jackson.core.util.DefaultIndenter;
2526
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
2627
import com.fasterxml.jackson.databind.DeserializationFeature;
@@ -41,7 +42,7 @@
4142
import org.springframework.ai.util.JacksonUtils;
4243
import org.springframework.core.KotlinDetector;
4344
import org.springframework.core.ParameterizedTypeReference;
44-
import org.springframework.lang.NonNull;
45+
import org.springframework.lang.Nullable;
4546

4647
import static org.springframework.ai.util.LoggingMarkers.SENSITIVE_DATA_MARKER;
4748

@@ -105,7 +106,8 @@ public BeanOutputConverter(Class<T> clazz, ObjectMapper objectMapper) {
105106
* @param objectMapper Custom object mapper for JSON operations.
106107
* @param textCleaner Custom text cleaner for preprocessing responses.
107108
*/
108-
public BeanOutputConverter(Class<T> clazz, ObjectMapper objectMapper, ResponseTextCleaner textCleaner) {
109+
public BeanOutputConverter(Class<T> clazz, @Nullable ObjectMapper objectMapper,
110+
@Nullable ResponseTextCleaner textCleaner) {
109111
this(ParameterizedTypeReference.forType(clazz), objectMapper, textCleaner);
110112
}
111113

@@ -135,8 +137,8 @@ public BeanOutputConverter(ParameterizedTypeReference<T> typeRef, ObjectMapper o
135137
* @param objectMapper Custom object mapper for JSON operations.
136138
* @param textCleaner Custom text cleaner for preprocessing responses.
137139
*/
138-
public BeanOutputConverter(ParameterizedTypeReference<T> typeRef, ObjectMapper objectMapper,
139-
ResponseTextCleaner textCleaner) {
140+
public BeanOutputConverter(ParameterizedTypeReference<T> typeRef, @Nullable ObjectMapper objectMapper,
141+
@Nullable ResponseTextCleaner textCleaner) {
140142
this(typeRef.getType(), objectMapper, textCleaner);
141143
}
142144

@@ -148,7 +150,8 @@ public BeanOutputConverter(ParameterizedTypeReference<T> typeRef, ObjectMapper o
148150
* @param objectMapper Custom object mapper for JSON operations. endings.
149151
* @param textCleaner Custom text cleaner for preprocessing responses.
150152
*/
151-
private BeanOutputConverter(Type type, ObjectMapper objectMapper, ResponseTextCleaner textCleaner) {
153+
private BeanOutputConverter(Type type, @Nullable ObjectMapper objectMapper,
154+
@Nullable ResponseTextCleaner textCleaner) {
152155
Objects.requireNonNull(type, "Type cannot be null;");
153156
this.type = type;
154157
this.objectMapper = objectMapper != null ? objectMapper : getObjectMapper();
@@ -217,14 +220,13 @@ private void generateSchema() {
217220
* @param text The LLM output in string format.
218221
* @return The parsed output in the desired target type.
219222
*/
220-
@SuppressWarnings("unchecked")
221223
@Override
222-
public T convert(@NonNull String text) {
224+
public T convert(String text) {
223225
try {
224226
// Clean the text using the configured text cleaner
225227
text = this.textCleaner.clean(text);
226228

227-
return (T) this.objectMapper.readValue(text, this.objectMapper.constructType(this.type));
229+
return this.objectMapper.readValue(text, this.objectMapper.constructType(this.type));
228230
}
229231
catch (JsonProcessingException e) {
230232
logger.error(SENSITIVE_DATA_MARKER,
@@ -272,12 +274,16 @@ public String getJsonSchema() {
272274

273275
public Map<String, Object> getJsonSchemaMap() {
274276
try {
275-
return this.objectMapper.readValue(this.jsonSchema, Map.class);
277+
return this.objectMapper.readValue(this.jsonSchema, new MapTypeReference());
276278
}
277279
catch (JsonProcessingException ex) {
278280
logger.error("Could not parse the JSON Schema to a Map object", ex);
279281
throw new IllegalStateException(ex);
280282
}
281283
}
282284

285+
private static final class MapTypeReference extends TypeReference<Map<String, Object>> {
286+
287+
}
288+
283289
}

spring-ai-model/src/main/java/org/springframework/ai/converter/CompositeResponseTextCleaner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2024 the original author or authors.
2+
* Copyright 2025-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

spring-ai-model/src/main/java/org/springframework/ai/converter/MarkdownCodeBlockCleaner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2024 the original author or authors.
2+
* Copyright 2025-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

spring-ai-model/src/main/java/org/springframework/ai/converter/ResponseTextCleaner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2024 the original author or authors.
2+
* Copyright 2025-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

spring-ai-model/src/main/java/org/springframework/ai/converter/ThinkingTagCleaner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2024 the original author or authors.
2+
* Copyright 2025-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

spring-ai-model/src/main/java/org/springframework/ai/converter/WhitespaceCleaner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2024 the original author or authors.
2+
* Copyright 2025-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

spring-ai-model/src/test/java/org/springframework/ai/converter/BeanOutputConverterTest.java

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2024 the original author or authors.
2+
* Copyright 2023-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,9 +33,6 @@
3333
import org.junit.jupiter.api.BeforeEach;
3434
import org.junit.jupiter.api.Nested;
3535
import org.junit.jupiter.api.Test;
36-
import org.junit.jupiter.api.extension.ExtendWith;
37-
import org.mockito.Mock;
38-
import org.mockito.junit.jupiter.MockitoExtension;
3936
import org.slf4j.LoggerFactory;
4037

4138
import org.springframework.ai.util.TextBlockAssertion;
@@ -52,17 +49,12 @@
5249
* @author Soby Chacko
5350
* @author Konstantin Pavlov
5451
*/
55-
@ExtendWith(MockitoExtension.class)
5652
class BeanOutputConverterTest {
5753

5854
private ListAppender<ILoggingEvent> logAppender;
5955

60-
@Mock
61-
private ObjectMapper objectMapperMock;
62-
6356
@BeforeEach
6457
void beforeEach() {
65-
6658
var logger = (Logger) LoggerFactory.getLogger(BeanOutputConverter.class);
6759

6860
this.logAppender = new ListAppender<>();
@@ -83,19 +75,15 @@ static class TestClass {
8375

8476
private String someString;
8577

86-
@SuppressWarnings("unused")
8778
TestClass() {
8879
}
8980

90-
TestClass(String someString) {
91-
this.someString = someString;
92-
}
93-
9481
String getSomeString() {
9582
return this.someString;
9683
}
9784

98-
public void setSomeString(String someString) {
85+
@SuppressWarnings("unused")
86+
void setSomeString(String someString) {
9987
this.someString = someString;
10088
}
10189

@@ -105,19 +93,15 @@ static class TestClassWithDateProperty {
10593

10694
private LocalDate someString;
10795

108-
@SuppressWarnings("unused")
10996
TestClassWithDateProperty() {
11097
}
11198

112-
TestClassWithDateProperty(LocalDate someString) {
113-
this.someString = someString;
114-
}
115-
11699
LocalDate getSomeString() {
117100
return this.someString;
118101
}
119102

120-
public void setSomeString(LocalDate someString) {
103+
@SuppressWarnings("unused")
104+
void setSomeString(LocalDate someString) {
121105
this.someString = someString;
122106
}
123107

spring-ai-model/src/test/java/org/springframework/ai/converter/CompositeResponseTextCleanerTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2024 the original author or authors.
2+
* Copyright 2025-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@ void shouldApplyCleanersInOrder() {
4141

4242
@Test
4343
void shouldWorkWithSingleCleaner() {
44-
var cleaner = new CompositeResponseTextCleaner(text -> text.trim());
44+
var cleaner = new CompositeResponseTextCleaner(String::trim);
4545
String result = cleaner.clean(" content ");
4646
assertThat(result).isEqualTo("content");
4747
}

spring-ai-model/src/test/java/org/springframework/ai/converter/ThinkingTagCleanerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2024 the original author or authors.
2+
* Copyright 2025-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

0 commit comments

Comments
 (0)