INT-3122 Return String Properties as String
Make converted object toString() behave as expected
This commit is contained in:
committed by
Gary Russell
parent
93f61160e2
commit
e24d683478
@@ -41,8 +41,8 @@ public class JsonPropertyAccessor implements PropertyAccessor {
|
||||
/**
|
||||
* The kind of types this can work with.
|
||||
*/
|
||||
private static final Class<?>[] SUPPORTED_CLASSES =
|
||||
new Class[] { String.class, ObjectNode.class, ArrayNode.class };
|
||||
private static final Class<?>[] SUPPORTED_CLASSES = new Class[] { String.class, ToStringFriendlyJsonNode.class,
|
||||
ObjectNode.class, ArrayNode.class };
|
||||
|
||||
// Note: ObjectMapper is thread-safe
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
@@ -59,20 +59,28 @@ public class JsonPropertyAccessor implements PropertyAccessor {
|
||||
return ((index != null && container.has(index)) || container.has(name));
|
||||
}
|
||||
|
||||
private ContainerNode<?> assertContainerNode(JsonNode json) throws AccessException {
|
||||
if (json instanceof ContainerNode) {
|
||||
return (ContainerNode<?>) json;
|
||||
}
|
||||
else {
|
||||
throw new AccessException("Can not act on json that is not a ContainerNode: "
|
||||
+ json.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
private ContainerNode<?> asJson(Object target) throws AccessException {
|
||||
if (target instanceof ContainerNode) {
|
||||
return (ContainerNode<?>) target;
|
||||
}
|
||||
else if (target instanceof ToStringFriendlyJsonNode) {
|
||||
ToStringFriendlyJsonNode wrapper = (ToStringFriendlyJsonNode) target;
|
||||
return assertContainerNode(wrapper.node);
|
||||
}
|
||||
else if (target instanceof String) {
|
||||
try {
|
||||
JsonNode json = this.objectMapper.readTree((String) target);
|
||||
if (json instanceof ContainerNode) {
|
||||
return (ContainerNode<?>) json;
|
||||
}
|
||||
else {
|
||||
throw new AccessException("Can not act on json that is not a ContainerNode: "
|
||||
+ json.getClass().getSimpleName());
|
||||
}
|
||||
return assertContainerNode(json);
|
||||
}
|
||||
catch (JsonProcessingException e) {
|
||||
throw new AccessException("Exception while trying to deserialize String", e);
|
||||
@@ -103,10 +111,10 @@ public class JsonPropertyAccessor implements PropertyAccessor {
|
||||
ContainerNode<?> container = asJson(target);
|
||||
Integer index = maybeIndex(name);
|
||||
if (index != null && container.has(index)) {
|
||||
return new TypedValue(container.get(index));
|
||||
return new TypedValue(wrap(container.get(index)));
|
||||
}
|
||||
else {
|
||||
return new TypedValue(container.get(name));
|
||||
return new TypedValue(wrap(container.get(name)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,4 +133,28 @@ public class JsonPropertyAccessor implements PropertyAccessor {
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
private ToStringFriendlyJsonNode wrap(JsonNode json) {
|
||||
return new ToStringFriendlyJsonNode(json);
|
||||
}
|
||||
|
||||
public static class ToStringFriendlyJsonNode {
|
||||
private final JsonNode node;
|
||||
|
||||
public ToStringFriendlyJsonNode(JsonNode node) {
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (node.isValueNode()) {
|
||||
// This is to avoid quotes around a TextNode for example
|
||||
return node.asText();
|
||||
}
|
||||
else {
|
||||
return node.toString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -49,20 +48,20 @@ public class JsonPropertyAccessorTests {
|
||||
@Test
|
||||
public void testSimpleLookup() throws Exception {
|
||||
Object json = mapper.readTree("{\"foo\": \"bar\"}");
|
||||
JsonNode actual = evaluate(json, "foo", JsonNode.class);
|
||||
assertEquals("bar", actual.asText());
|
||||
Object actual = evaluate(json, "foo", Object.class);
|
||||
assertEquals("bar", actual.toString());
|
||||
}
|
||||
|
||||
@Test(expected = SpelEvaluationException.class)
|
||||
public void testUnsupportedJsonConstruct() throws Exception {
|
||||
Object json = mapper.readTree("\"foo\"");
|
||||
evaluate(json, "fizz", JsonNode.class);
|
||||
evaluate(json, "fizz", Object.class);
|
||||
}
|
||||
|
||||
@Test(expected = SpelEvaluationException.class)
|
||||
public void testMissingProperty() throws Exception {
|
||||
Object json = mapper.readTree("{\"foo\": \"bar\"}");
|
||||
evaluate(json, "fizz", JsonNode.class);
|
||||
evaluate(json, "fizz", Object.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -70,8 +69,8 @@ public class JsonPropertyAccessorTests {
|
||||
Object json = mapper.readTree("[3, 4, 5]");
|
||||
// JsonNode actual = evaluate("1", json, JsonNode.class); // Does not work
|
||||
// JsonNode actual = evaluate("'1'", json, JsonNode.class); // Does not work
|
||||
JsonNode actual = evaluate(json, "['1']", JsonNode.class);
|
||||
assertEquals(4, actual.asInt());
|
||||
Object actual = evaluate(json, "['1']", Object.class);
|
||||
assertEquals("4", actual.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -79,22 +78,22 @@ public class JsonPropertyAccessorTests {
|
||||
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
|
||||
JsonNode actual = evaluate(json, "['1']['1']", JsonNode.class);
|
||||
assertEquals(5, actual.asInt());
|
||||
Object actual = evaluate(json, "['1']['1']", Object.class);
|
||||
assertEquals("5", actual.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNestedHashConstruct() throws Exception {
|
||||
Object json = mapper.readTree("{\"foo\": {\"bar\": 4, \"fizz\": 5} }");
|
||||
JsonNode actual = evaluate(json, "foo.fizz", JsonNode.class);
|
||||
assertEquals(5, actual.asInt());
|
||||
Object actual = evaluate(json, "foo.fizz", Object.class);
|
||||
assertEquals("5", actual.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImplicitStringConversion() throws Exception {
|
||||
String json = "{\"foo\": {\"bar\": 4, \"fizz\": 5} }";
|
||||
JsonNode actual = evaluate(json, "foo.fizz", JsonNode.class);
|
||||
assertEquals(5, actual.asInt());
|
||||
Object actual = evaluate(json, "foo.fizz", Object.class);
|
||||
assertEquals("5", actual.toString());
|
||||
}
|
||||
|
||||
@Test(expected = SpelEvaluationException.class)
|
||||
|
||||
Reference in New Issue
Block a user