INT-4241: Wrap ArrayNodes with ArrayNodeAsList

JIRA: https://jira.spring.io/browse/INT-4241

To allow `ArrayNode` to be treated as `List` in SpEL expressions, wrap them to the internal `ArrayNodeAsList` implementation

Fix Checkstyle errors

* Add `iterator()` support to the `ArrayNodeAsList`
This commit is contained in:
Paul Martin
2017-03-06 23:22:22 +00:00
committed by Artem Bilan
parent 76cbed649c
commit 85aead337f
2 changed files with 150 additions and 18 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,8 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
@@ -30,13 +32,16 @@ import org.springframework.expression.spel.SpelEvaluationException;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
/**
* Tests for {@link JsonPropertyAccessor}.
*
* @author Eric Bottard
* @author Artem Bilan
* @author Paul Martin
* @since 3.0
*/
public class JsonPropertyAccessorTests {
@@ -79,8 +84,28 @@ public class JsonPropertyAccessorTests {
@Test
public void testArrayLookup() throws Exception {
Object json = mapper.readTree("[3, 4, 5]");
ArrayNode json = (ArrayNode) mapper.readTree("[3, 4, 5]");
// JsonNode actual = evaluate("1", json, JsonNode.class); // Does not work
// Have to wrap the root array because ArrayNode itself is not a container
Object actual = evaluate(JsonPropertyAccessor.wrap(json), "[1]", Object.class);
assertEquals("4", actual.toString());
}
@Test
public void testArrayNegativeIndex() throws Exception {
JsonNode json = mapper.readTree("{\"foo\":[3, 4, 5]}");
assertNull(evaluate(json, "foo[-1]", Object.class));
}
@Test(expected = SpelEvaluationException.class)
public void testArrayIndexOutOfBounds() throws Exception {
JsonNode json = mapper.readTree("{\"foo\":[3, 4, 5]}");
evaluate(json, "foo[3]", Object.class);
}
@Test
public void testArrayLookupWithStringIndex() throws Exception {
Object json = mapper.readTree("[3, 4, 5]");
// JsonNode actual = evaluate("'1'", json, JsonNode.class); // Does not work
Object actual = evaluate(json, "['1']", Object.class);
assertEquals("4", actual.toString());
@@ -88,13 +113,42 @@ public class JsonPropertyAccessorTests {
@Test
public void testNestedArrayConstruct() throws Exception {
ArrayNode json = (ArrayNode) mapper.readTree("[[3], [4, 5], []]");
// JsonNode actual = evaluate("1.1", json, JsonNode.class); // Does not work
Object actual = evaluate(JsonPropertyAccessor.wrap(json), "[1][1]", Object.class);
assertEquals("5", actual.toString());
}
@Test
public void testNestedArrayConstructWithStringIndex() throws Exception {
Object json = mapper.readTree("[[3], [4, 5], []]");
// JsonNode actual = evaluate("1.1", json, JsonNode.class); // Does not work
// JsonNode actual = evaluate("[1][1]", json, JsonNode.class); // Does not work
Object actual = evaluate(json, "['1']['1']", Object.class);
assertEquals("5", actual.toString());
}
@Test
public void testArrayResult() throws Exception {
Object json = mapper.readTree(
"{\"foo\": {\"bar\": [ { \"fizz\": 5, \"buzz\": 6 }, {\"fizz\": 7}, {\"fizz\": 8} ] } }");
// Filter the bar array to return only the fizz value of each element (to prove that SPeL considers bar
// an array/list)
List<?> actualArray = evaluate(json, "foo.bar.![fizz]", List.class);
assertEquals("Array size", 3, actualArray.size());
assertEquals("[0]", "5", evaluate(actualArray, "[0]", Object.class).toString());
assertEquals("[1]", "7", evaluate(actualArray, "[1]", Object.class).toString());
assertEquals("[2]", "8", evaluate(actualArray, "[2]", Object.class).toString());
}
@Test
public void testEmptyArrayResult() throws Exception {
Object json = mapper.readTree(
"{\"foo\": {\"bar\": [ { \"fizz\": 5, \"buzz\": 6 }, {\"fizz\": 7}, {\"fizz\": 8} ] } }");
// Filter bar objects so that none match
List<?> actualArray = evaluate(json, "foo.bar.?[fizz=='0']", List.class);
assertEquals(0, actualArray.size());
}
@Test
public void testNestedHashConstruct() throws Exception {
Object json = mapper.readTree("{\"foo\": {\"bar\": 4, \"fizz\": 5} }");