11/*
2- * Copyright 2013-2023 the original author or authors.
2+ * Copyright 2013-2024 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.
2424import com .fasterxml .jackson .databind .JsonNode ;
2525import com .fasterxml .jackson .databind .ObjectMapper ;
2626import com .fasterxml .jackson .databind .node .ArrayNode ;
27+ import com .fasterxml .jackson .databind .node .NullNode ;
2728
2829import org .springframework .expression .AccessException ;
2930import org .springframework .expression .EvaluationContext ;
3536
3637/**
3738 * A SpEL {@link PropertyAccessor} that knows how to read properties from JSON objects.
38- * Uses Jackson {@link JsonNode} API for nested properties access.
39+ * <p> Uses Jackson {@link JsonNode} API for nested properties access.
3940 *
4041 * @author Eric Bottard
4142 * @author Artem Bilan
4243 * @author Paul Martin
4344 * @author Gary Russell
4445 * @author Pierre Lakreb
4546 * @author Vladislav Fefelov
47+ * @author Sam Brannen
4648 *
4749 * @since 3.0
50+ * @see JsonIndexAccessor
4851 */
4952public class JsonPropertyAccessor implements PropertyAccessor {
5053
@@ -80,23 +83,22 @@ public boolean canRead(EvaluationContext context, Object target, String name) th
8083 // Cannot parse - treat as not a JSON
8184 return false ;
8285 }
83- Integer index = maybeIndex (name );
8486 if (node instanceof ArrayNode ) {
85- return index != null ;
87+ return maybeIndex ( name ) != null ;
8688 }
8789 return true ;
8890 }
8991
9092 private JsonNode asJson (Object target ) throws AccessException {
91- if (target instanceof JsonNode ) {
92- return ( JsonNode ) target ;
93+ if (target instanceof JsonNode jsonNode ) {
94+ return jsonNode ;
9395 }
94- else if (target instanceof JsonNodeWrapper ) {
95- return (( JsonNodeWrapper <?>) target ) .getRealNode ();
96+ else if (target instanceof JsonNodeWrapper <?> jsonNodeWrapper ) {
97+ return jsonNodeWrapper .getRealNode ();
9698 }
97- else if (target instanceof String ) {
99+ else if (target instanceof String content ) {
98100 try {
99- return this .objectMapper .readTree (( String ) target );
101+ return this .objectMapper .readTree (content );
100102 }
101103 catch (JsonProcessingException e ) {
102104 throw new AccessException ("Exception while trying to deserialize String" , e );
@@ -160,8 +162,8 @@ private static boolean isNumeric(String str) {
160162 return true ;
161163 }
162164
163- private static TypedValue typedValue (JsonNode json ) throws AccessException {
164- if (json == null ) {
165+ static TypedValue typedValue (JsonNode json ) throws AccessException {
166+ if (json == null || json instanceof NullNode ) {
165167 return TypedValue .NULL ;
166168 }
167169 else if (json .isValueNode ()) {
@@ -199,8 +201,8 @@ public static Object wrap(JsonNode json) throws AccessException {
199201 if (json == null ) {
200202 return null ;
201203 }
202- else if (json instanceof ArrayNode ) {
203- return new ArrayNodeAsList (( ArrayNode ) json );
204+ else if (json instanceof ArrayNode arrayNode ) {
205+ return new ArrayNodeAsList (arrayNode );
204206 }
205207 else if (json .isValueNode ()) {
206208 return getValue (json );
@@ -212,8 +214,6 @@ else if (json.isValueNode()) {
212214
213215 interface JsonNodeWrapper <T > extends Comparable <T > {
214216
215- String toString ();
216-
217217 JsonNode getRealNode ();
218218
219219 }
@@ -309,10 +309,8 @@ public Object next() {
309309
310310 @ Override
311311 public int compareTo (Object o ) {
312- if (o instanceof JsonNodeWrapper <?>) {
313- return this .delegate .equals (((JsonNodeWrapper <?>) o ).getRealNode ()) ? 0 : 1 ;
314- }
315- return this .delegate .equals (o ) ? 0 : 1 ;
312+ Object that = (o instanceof JsonNodeWrapper <?> wrapper ? wrapper .getRealNode () : o );
313+ return this .delegate .equals (that ) ? 0 : 1 ;
316314 }
317315
318316 }
0 commit comments