11/*
2- * Copyright 2013-2017 the original author or authors.
2+ * Copyright 2013-2018 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.
3434import com .fasterxml .jackson .databind .node .ObjectNode ;
3535
3636/**
37- * A SpEL {@link PropertyAccessor} that knows how to read on Jackson JSON objects.
37+ * A SpEL {@link PropertyAccessor} that knows how to read properties from JSON objects.
38+ * Uses Jackson {@link JsonNode} API for nested properties access.
3839 *
3940 * @author Eric Bottard
4041 * @author Artem Bilan
4142 * @author Paul Martin
43+ *
4244 * @since 3.0
4345 */
4446public class JsonPropertyAccessor implements PropertyAccessor {
4547
4648 /**
4749 * The kind of types this can work with.
4850 */
49- private static final Class <?>[] SUPPORTED_CLASSES = new Class <?>[] { String .class , ToStringFriendlyJsonNode .class ,
50- ArrayNodeAsList .class , ObjectNode .class , ArrayNode .class };
51+ private static final Class <?>[] SUPPORTED_CLASSES =
52+ new Class <?>[] {
53+ String .class ,
54+ ToStringFriendlyJsonNode .class ,
55+ ArrayNodeAsList .class ,
56+ ObjectNode .class ,
57+ ArrayNode .class
58+ };
5159
5260 // Note: ObjectMapper is thread-safe
5361 private ObjectMapper objectMapper = new ObjectMapper ();
5462
63+ public void setObjectMapper (ObjectMapper objectMapper ) {
64+ Assert .notNull (objectMapper , "'objectMapper' cannot be null" );
65+ this .objectMapper = objectMapper ;
66+ }
67+
5568 @ Override
5669 public Class <?>[] getSpecificTargetClasses () {
5770 return SUPPORTED_CLASSES ;
@@ -133,20 +146,15 @@ public TypedValue read(EvaluationContext context, Object target, String name) th
133146 }
134147
135148 @ Override
136- public boolean canWrite (EvaluationContext context , Object target , String name ) throws AccessException {
149+ public boolean canWrite (EvaluationContext context , Object target , String name ) {
137150 return false ;
138151 }
139152
140153 @ Override
141- public void write (EvaluationContext context , Object target , String name , Object newValue ) throws AccessException {
154+ public void write (EvaluationContext context , Object target , String name , Object newValue ) {
142155 throw new UnsupportedOperationException ("Write is not supported" );
143156 }
144157
145- public void setObjectMapper (ObjectMapper objectMapper ) {
146- Assert .notNull (objectMapper , "'objectMapper' cannot be null" );
147- this .objectMapper = objectMapper ;
148- }
149-
150158 private static TypedValue typedValue (JsonNode json ) {
151159 if (json == null ) {
152160 return TypedValue .NULL ;
@@ -172,21 +180,32 @@ else if (json instanceof ArrayNode) {
172180 * The base interface for wrapped {@link JsonNode}.
173181 * @since 5.0
174182 */
175- public interface WrappedJsonNode {
183+ public interface WrappedJsonNode <T extends JsonNode > {
184+
185+ /**
186+ * Return the wrapped {@link JsonNode}
187+ * @return the wrapped JsonNode
188+ */
189+ T getTarget ();
176190
177191 }
178192
179193 /**
180194 * A {@link WrappedJsonNode} implementation to represent {@link JsonNode} as string.
181195 */
182- public static class ToStringFriendlyJsonNode implements WrappedJsonNode {
196+ public static class ToStringFriendlyJsonNode implements WrappedJsonNode < JsonNode > {
183197
184198 private final JsonNode node ;
185199
186200 ToStringFriendlyJsonNode (JsonNode node ) {
187201 this .node = node ;
188202 }
189203
204+ @ Override
205+ public JsonNode getTarget () {
206+ return this .node ;
207+ }
208+
190209 @ Override
191210 public String toString () {
192211 if (this .node == null ) {
@@ -224,14 +243,19 @@ public int hashCode() {
224243 * An {@link AbstractList} implementation around {@link ArrayNode} with {@link WrappedJsonNode} aspect.
225244 * @since 5.0
226245 */
227- public static class ArrayNodeAsList extends AbstractList <WrappedJsonNode > implements WrappedJsonNode {
246+ public static class ArrayNodeAsList extends AbstractList <WrappedJsonNode > implements WrappedJsonNode < ArrayNode > {
228247
229248 private final ArrayNode node ;
230249
231250 ArrayNodeAsList (ArrayNode node ) {
232251 this .node = node ;
233252 }
234253
254+ @ Override
255+ public ArrayNode getTarget () {
256+ return this .node ;
257+ }
258+
235259 @ Override
236260 public WrappedJsonNode get (int index ) {
237261 return wrap (this .node .get (index ));
0 commit comments