@ -1,11 +1,21 @@
[[expressions-properties-arrays]]
[[expressions-properties-arrays]]
= Properties, Arrays, Lists, Maps, and Indexers
= Properties, Arrays, Lists, Maps, and Indexers
Navigating with property references is easy. To do so, use a period to indicate a nested
The Spring Expression Language provides support for navigating object graphs and indexing
property value. The instances of the `Inventor` class, `pupin` and `tesla`, were
into various structures.
populated with data listed in the xref:core/expressions/example-classes.adoc[Classes used in the examples]
section. To navigate "down" the object graph and get Tesla's year of birth and
NOTE: Numerical index values are zero-based, such as when accessing the n^th^ element of
Pupin's city of birth, we use the following expressions:
an array in Java.
[[expressions-property-navigation]]
== Property Navigation
You can navigate property references within an object graph by using a period to indicate
a nested property value. The instances of the `Inventor` class, `pupin` and `tesla`, were
populated with data listed in the
xref:core/expressions/example-classes.adoc[Classes used in the examples] section. To
navigate _down_ the object graph and get Tesla's year of birth and Pupin's city of birth,
we use the following expressions:
[tabs]
[tabs]
======
======
@ -16,6 +26,7 @@ Java::
// evaluates to 1856
// evaluates to 1856
int year = (Integer) parser.parseExpression("birthdate.year + 1900").getValue(context);
int year = (Integer) parser.parseExpression("birthdate.year + 1900").getValue(context);
// evaluates to "Smiljan"
String city = (String) parser.parseExpression("placeOfBirth.city").getValue(context);
String city = (String) parser.parseExpression("placeOfBirth.city").getValue(context);
----
----
@ -26,6 +37,7 @@ Kotlin::
// evaluates to 1856
// evaluates to 1856
val year = parser.parseExpression("birthdate.year + 1900").getValue(context) as Int
val year = parser.parseExpression("birthdate.year + 1900").getValue(context) as Int
// evaluates to "Smiljan"
val city = parser.parseExpression("placeOfBirth.city").getValue(context) as String
val city = parser.parseExpression("placeOfBirth.city").getValue(context) as String
----
----
======
======
@ -39,8 +51,20 @@ method invocations -- for example, `getPlaceOfBirth().getCity()` instead of
`placeOfBirth.city`.
`placeOfBirth.city`.
====
====
The contents of arrays and lists are obtained by using square bracket notation, as the
[[expressions-indexing-arrays-and-collections]]
following example shows:
== Indexing into Arrays and Collections
The n^th^ element of an array or collection (for example, a `Set` or `List`) can be
obtained by using square bracket notation, as the following example shows.
[NOTE]
====
If the indexed collection is a `java.util.List`, the n^th^ element will be accessed
directly via `list.get(n)`.
For any other type of `Collection`, the n^th^ element will be accessed by iterating over
the collection using its `Iterator` and returning the n^th^ element encountered.
====
[tabs]
[tabs]
======
======
@ -63,7 +87,8 @@ Java::
String name = parser.parseExpression("members[0].name").getValue(
String name = parser.parseExpression("members[0].name").getValue(
context, ieee, String.class);
context, ieee, String.class);
// List and Array navigation
// List and Array Indexing
// evaluates to "Wireless communication"
// evaluates to "Wireless communication"
String invention = parser.parseExpression("members[0].inventions[6]").getValue(
String invention = parser.parseExpression("members[0].inventions[6]").getValue(
context, ieee, String.class);
context, ieee, String.class);
@ -88,16 +113,22 @@ Kotlin::
val name = parser.parseExpression("members[0].name").getValue(
val name = parser.parseExpression("members[0].name").getValue(
context, ieee, String::class.java)
context, ieee, String::class.java)
// List and Array navigation
// List and Array Indexing
// evaluates to "Wireless communication"
// evaluates to "Wireless communication"
val invention = parser.parseExpression("members[0].inventions[6]").getValue(
val invention = parser.parseExpression("members[0].inventions[6]").getValue(
context, ieee, String::class.java)
context, ieee, String::class.java)
----
----
======
======
The contents of maps are obtained by specifying the literal key value within the
[[expressions-indexing-strings]]
brackets. In the following example, because keys for the `officers` map are strings, we can specify
== Indexing into Strings
string literals:
The n^th^ character of a string can be obtained by specifying the index within square
brackets, as demonstrated in the following example.
NOTE: The n^th^ character of a string will evaluate to a `java.lang.String`, not a
`java.lang.Character`.
[tabs]
[tabs]
======
======
@ -105,38 +136,113 @@ Java::
+
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
----
// Officer's Dictionary
// evaluates to "T" (8th letter of "Nikola Tesla")
String character = parser.parseExpression("members[0].name[7]")
.getValue(societyContext, String.class);
----
Inventor pupin = parser.parseExpression("officers['president']").getValue(
Kotlin::
societyContext, Inventor.class);
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
// evaluates to "T" (8th letter of "Nikola Tesla")
val character = parser.parseExpression("members[0].name[7]")
.getValue(societyContext, String::class.java)
----
======
[[expressions-indexing-maps]]
== Indexing into Maps
The contents of maps are obtained by specifying the key value within square brackets. In
the following example, because keys for the `officers` map are strings, we can specify
string literals such as `'president'`:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
// Officer's Map
// evaluates to Inventor("Pupin")
Inventor pupin = parser.parseExpression("officers['president']")
.getValue(societyContext, Inventor.class);
// evaluates to "Idvor"
// evaluates to "Idvor"
String city = parser.parseExpression("officers['president'].placeOfBirth.city").getValue(
String city = parser.parseExpression("officers['president'].placeOfBirth.city")
societyContext, String.class);
.getValue(societyContext, String.class);
String countryExpression = "officers['advisors'][0].placeOfBirth.country";
// setting values
// setting values
parser.parseExpression("officers['advisors'][0].placeOfBirth.country").setValue(
parser.parseExpression(countryExpression)
societyContext, "Croatia");
.setValue(societyContext, "Croatia");
// evaluates to "Croatia"
String country = parser.parseExpression(countryExpression)
.getValue(societyContext, String.class);
----
----
Kotlin::
Kotlin::
+
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
----
// Officer's Dictionary
// Officer's Map
val pupin = parser.parseExpression("officers['president']").getValue(
// evaluates to Inventor("Pupin")
societyContext, Inventor::class.java)
val pupin = parser.parseExpression("officers['president']")
.getValue(societyContext, Inventor::class.java)
// evaluates to "Idvor"
// evaluates to "Idvor"
val city = parser.parseExpression("officers['president'].placeOfBirth.city").getValue(
val city = parser.parseExpression("officers['president'].placeOfBirth.city")
societyContext, String::class.java)
.getValue(societyContext, String::class.java)
val countryExpression = "officers['advisors'][0].placeOfBirth.country"
// setting values
// setting values
parser.parseExpression("officers['advisors'][0].placeOfBirth.country").setValue(
parser.parseExpression(countryExpression)
societyContext, "Croatia")
.setValue(societyContext, "Croatia")
// evaluates to "Croatia"
val country = parser.parseExpression(countryExpression)
.getValue(societyContext, String::class.java)
----
----
======
======
[[expressions-indexing-objects]]
== Indexing into Objects
A property of an object can be obtained by specifying the name of the property within
square brackets. This is analogous to accessing the value of a map based on its key. The
following example demonstrates how to _index_ into an object to retrieve a specific
property.
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
// Create an inventor to use as the root context object.
Inventor tesla = new Inventor("Nikola Tesla");
// evaluates to "Nikola Tesla"
String name = parser.parseExpression("#root['name']")
.getValue(context, tesla, String.class);
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
// Create an inventor to use as the root context object.
val tesla = Inventor("Nikola Tesla")
// evaluates to "Nikola Tesla"
val name = parser.parseExpression("#root['name']")
.getValue(context, tesla, String::class.java)
----
======