Skip to content

Commit b192d52

Browse files
committed
GH-10058: Add SpEL JSON accessors and converter with Jackson 3
Related to: #10058 * Add `JsonNodePropertyAccessor` for reading JSON object properties * Add `JsonArrayNodeIndexAccessor` for array index access * Add `JsonNodeWrapperConverter` for type conversion between `JsonNodeWrapper` and `JsonNode` * Add `EmbeddedJsonMessageHeadersMessageMapper` for JSON message serialization with embedded headers * Deprecate Jackson 2 SpEL JSON accessors Signed-off-by: Jooyoung Pyoung <[email protected]>
1 parent 911ddd3 commit b192d52

15 files changed

+1471
-1
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ configure(javaProjects) { subproject ->
259259

260260
tasks.withType(Javadoc) {
261261
options.addBooleanOption('Xdoclint:syntax', true) // only check syntax with doclint
262-
options.addBooleanOption('Werror', true) // fail build on Javadoc warnings
262+
// TODO until deprecation cleanup options.addBooleanOption('Werror', true) // fail build on Javadoc warnings
263263
}
264264

265265
tasks.withType(JavaForkOptions) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2025-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.integration.json;
18+
19+
import org.jspecify.annotations.Nullable;
20+
import tools.jackson.databind.node.ArrayNode;
21+
22+
import org.springframework.expression.AccessException;
23+
import org.springframework.expression.EvaluationContext;
24+
import org.springframework.expression.IndexAccessor;
25+
import org.springframework.expression.TypedValue;
26+
27+
/**
28+
* A SpEL {@link IndexAccessor} that knows how to read indexes from JSON arrays, using
29+
* Jackson's {@link ArrayNode} API.
30+
*
31+
* <p>Supports indexes supplied as an integer literal &mdash; for example, {@code myJsonArray[1]}.
32+
* Also supports negative indexes &mdash; for example, {@code myJsonArray[-1]} which equates
33+
* to {@code myJsonArray[myJsonArray.length - 1]}. Furthermore, {@code null} is returned for
34+
* any index that is out of bounds (see {@link ArrayNode#get(int)} for details).
35+
*
36+
* @author Jooyoung Pyoung
37+
*
38+
* @since 7.0
39+
* @see JsonNodePropertyAccessor
40+
*/
41+
public class JsonArrayNodeIndexAccessor implements IndexAccessor {
42+
43+
private static final Class<?>[] SUPPORTED_CLASSES = { ArrayNode.class };
44+
45+
@Override
46+
public Class<?>[] getSpecificTargetClasses() {
47+
return SUPPORTED_CLASSES;
48+
}
49+
50+
@Override
51+
public boolean canRead(EvaluationContext context, Object target, Object index) {
52+
return (target instanceof ArrayNode && index instanceof Integer);
53+
}
54+
55+
@Override
56+
public TypedValue read(EvaluationContext context, Object target, Object index) throws AccessException {
57+
ArrayNode arrayNode = (ArrayNode) target;
58+
Integer intIndex = (Integer) index;
59+
if (intIndex < 0) {
60+
// negative index: get from the end of array, for compatibility with JsonNodePropertyAccessor.ArrayNodeAsList.
61+
intIndex = arrayNode.size() + intIndex;
62+
}
63+
return JsonNodePropertyAccessor.typedValue(arrayNode.get(intIndex));
64+
}
65+
66+
@Override
67+
public boolean canWrite(EvaluationContext context, Object target, Object index) {
68+
return false;
69+
}
70+
71+
@Override
72+
public void write(EvaluationContext context, Object target, Object index, @Nullable Object newValue) {
73+
throw new UnsupportedOperationException("Write is not supported");
74+
}
75+
76+
}

spring-integration-core/src/main/java/org/springframework/integration/json/JsonIndexAccessor.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,12 @@
3434
* any index that is out of bounds (see {@link ArrayNode#get(int)} for details).
3535
*
3636
* @author Sam Brannen
37+
*
3738
* @since 6.4
3839
* @see JsonPropertyAccessor
40+
* @deprecated Since 7.0 in favor of {@link JsonArrayNodeIndexAccessor} for Jackson 3.
3941
*/
42+
@Deprecated(forRemoval = true, since = "7.0")
4043
public class JsonIndexAccessor implements IndexAccessor {
4144

4245
private static final Class<?>[] SUPPORTED_CLASSES = { ArrayNode.class };

0 commit comments

Comments
 (0)